Planète

Par flocondetoile
Adhérent

Des petits sites, des gros sites, des micro sites avec Drupal 8

Drupal 8 est un outil dimensionné pour répondre aux besoins des projets web les plus ambitieux. Nous entendons beaucoup parler des notions de headless, de API first, de découplage, etc. qui résolument permettent des architectures solides pour projets ambitieux. Mais ce n'est pas pour autant que Drupal 8 ne propulse plus des sites plus classiques, et voire parfois beaucoup moins ambitieux : de simples, petits, sites Internet, mais pour lesquels nous souhaitons bénéficier de la modularité, de la souplesse et de la robustesse de Drupal.

Par GoZ
Fabien CLEMENT

Installer un Drupal multilingue depuis la configuration

Installer un Drupal multilingue depuis la configuration

Depuis que nous n'avons plus besoin de features pour gérer la configuration et depuis que nous pouvons gérer cette configuration via les fichiers yaml dans un répertoire de configuration, il est beaucoup plus facile de maintenir une configuration entre différents environnements. Depuis quelques temps, il est possible d'installer sans module supplémentaire un Drupal en se basant sur une configuration existante.

GoZ
lun 10/12/2018 - 11:12

Par flocondetoile
Adhérent

Fournir un formulaire personnalisé aux entités de Drupal 8

A l'instar des modes d'affichage qui permettent d'afficher une entité de multiples manières, Drupal 8 permet de créer de multiples modes de saisie, ou formulaires, utilisables sur les entités, que ce soient les utilisateurs, les termes de taxonomy, les contenus ou n'importe quelle entité personnalisée. Découvrons ici comment utiliser ces modes de saisie, depuis leur création jusqu'à leur exploitation pour personnaliser la saisie par exemple des informations d'un utilisateur.

Par Artusamak
Julien Dubois

Créer un système d'annonces simple avec Drupal 8 (seconde partie)

Créer un système d'annonces simple avec Drupal 8 (seconde partie)
DuaelFr
mar 04/12/2018 - 09:30

La première partie de cet article décrivait l'analyse et l'implémentation du système d'annonce présent sur notre site. Dans cette partie nous aborderons l'affichage de l'annonce et la gestion du cache.

Corps

Dans la première partie de cet article, nous avons créé un formulaire qui nous permet de configurer une annonce, sa date de début, sa date de fin et son contenu. Désormais, il nous faut afficher ces informations en respectant la configuration, notamment les dates.

Pour afficher des informations dans une zone définie d'un site Drupal, en dehors de la zone de contenu, nous avons un mécanisme tout désigné : les blocs. Selon la demande initiale, nous devons donc créer un bloc qui sera présent sur toutes les pages du site, lorsque l'annonce est activée et que nous sommes entre la date de début et la date de fin de l'annonce.

Création du bloc

Nous l'avons déjà couvert dans les billets issus de notre formation, la création d'un bloc passe par la création d'un Plugin, soit la forme d'une classe PHP munie d'une Annotation. Dans notre cas, comme pour le formulaire de paramétrage, nous aurons besoin de pouvoir accéder aux données stockées dans la State API et nous aurons donc une dépendance à injecter. La différence principale est que la classe BlockBase n'implémente pas déjà l'interface nécessaire et qu'il faudra donc le faire nous même. Vous le constaterez, du fait que nous manipulions un Plugin et plus juste un formulaire, les méthodes create() et __construct() auront besoin de quelques paramètres complémentaires. Voyons voir ce que l'on doit mettre dans notre fichier src/Plugin/Block/Announcement.php.

namespace Drupal\hc_announce\Plugin\Block;

use Drupal\Core\Block\BlockBase;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\State\StateInterface;

/**
* Provides a 'Announcement' block.
*
* @Block(
*  id = "announcement",
*  admin_label = @Translation("Announcement"),
* )
*/
class Announcement extends BlockBase implements ContainerFactoryPluginInterface {

  /**
   * @var array
   */
  protected $config;

  /**
   * Constructs a new Announcement object.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param string $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\Core\State\StateInterface $state
   */
  public function __construct(
    array $configuration,
    $plugin_id,
    $plugin_definition,
    StateInterface $state
  ) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->config = $state->get('hc_announcement');
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('state')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function build() {
    return ['#markup' => 'Content of the block'];
  }

}

Bien, maintenant que le bloc est créé et après une petite vidange du cache, vous devriez le voir apparaître dans la liste des blocs disponibles dans l'administration du site. Une fois positionné dans la région de notre choix, on a bien la chaîne "Content of the block" qui apparaît sur le site. Tâchons de faire un petit peu mieux en affichant au moins le contenu stocké dans le State pour que les personnes en charge de l'intégration puissent commencer à travailler sur l'aspect visuel. Nous enrichissons donc la méthode build() de notre bloc comme suit.

  /**
   * {@inheritdoc}
   */
  public function build() {
    $build = [];

    $build['#title'] = $this->config['title'];
    $build['#attributes'] = [
      'class' => ['announcement'],
    ];

    $build['announcement'] = [
      '#type' => 'container',
      '#attributes' => ['class' => ['announcement__content']],
      'content' => [
        '#type' => 'processed_text',
        '#text' => $this->config['announcement']['value'],
        '#format' => $this->config['announcement']['format'],
      ],
    ];

    return $build;
  }

Cela fonctionne bien. Cependant, nous ne respectons pas l'état d'activation de l'annonce ni ses dates de début et de fin. Pour l'état de l'annonce rien de plus simple. Avec un test dans la méthode build(), il est toujours possible de renvoyer un tableau vide si l'annonce est inactive. Pour manipuler les dates, nous avons par contre besoin d'une nouvelle dépendance sur le service datetime.time du cœur. Nous ajoutons donc ce service à la méthode create(), à la méthode __construct() et l'enregistrons dans un attribut $time au niveau de l'objet. Puis, nous ajoutons le code suivant à la méthode build() pour renvoyer un bloc vide si le bloc n'est pas supposé être actif.

    if (empty($this->config['enabled'])) {
      return $build;
    }

    $now = $this->time->getRequestTime();
    $start = (new \DateTime($this->config['start_date'] . ' 00:00:00'))->getTimestamp();
    $end = (new \DateTime($this->config['end_date'] . ' 23:59:59'))->getTimestamp();
    if ($now < $start || $now > $end) {
      return $build;
    }

Trop facile ? Vous n'avez pas tort...

Le problème du cache

Comme indiqué en introduction de cet article, ce bloc va être visible sur toutes les pages du site. Il est donc particulièrement important de bien gérer son cache car sinon nous pouvons être confrontés à deux problématiques majeures :

  1. le bloc est affiché quand il est supposé être inactif ou ne s'affiche pas quand il est supposé être actif,
  2. aucune des pages du site n'est mise en cache.

Nous avions déjà abordé le sujet du cache dans Drupal 8 dans un précédent article sans toutefois aborder le cas un peu spécifique des blocs. En effet, ces derniers utilisent les mêmes métadonnées que les render arrays abordés dans l'article mais définies par des méthodes spécifiques : getCacheContexts(), getCacheMaxAge() et getCacheTags(). Ces dernières vont permettre d'indiquer au service BlockManager, comment mettre en cache le bloc dans son intégralité. Lors du rendu d'une page, si le BlockManager se voit demander un bloc qu'il considère comme ayant un cache valide, il va le renvoyer sans même tenter d'instancier sa classe ou d'appeler sa méthode build() ! Par défaut, tous les blocs sont mis en cache de façon permanente et sans aucune variante. Comme pour le reste des métadonnées de cache, ces dernières se propagent vers le conteneur. Il n'est donc pas souhaitable de se faciliter la vie en désactivant totalement le cache de notre bloc sinon cela signifierait désactiver le cache de toutes les pages du site (en vrai c'est mieux fait que ça, mais on simplifie un peu pour avancer).

Gérer la temporalité du cache

Dans notre cas bien particulier, nous allons devoir prévoir trois cas distincts :

  1. si la date de début n'est pas encore arrivée nous devons mettre en cache jusqu'à cette date,
  2. si la date de début est passée mais la date de fin pas encore, nous devons mettre en cache jusqu'à la date de fin,
  3. si la date de début et de fin sont passées ou si l'annonce est désactivée, nous devons mettre en cache de façon permanente.

Pour atteindre ce but, nous allons simplement implémenter la méthode getCacheMaxAge() de la façon suivante :

  /**
   * {@inheritdoc}
   */
  public function getCacheMaxAge() {
    $max_age = parent::getCacheMaxAge();
    if (!empty($this->config['enabled'])) {
      $now = $this->time->getRequestTime();
      $start = (new \DateTime($this->config['start_date'] . ' 00:00:00'))->getTimestamp();
      $end = (new \DateTime($this->config['end_date'] . ' 23:59:59'))->getTimestamp();

      if ($now < $start) {
        $max_age = Cache::mergeMaxAges($max_age, $start - $now);
      }
      elseif ($now < $end) {
        $max_age = Cache::mergeMaxAges($max_age, $end - $now);
      }
    }

    return $max_age;
  }

Notez l'usage de la méthode \Drupal\Core\Cache\Cache::mergeMaxAges() qui permet de proprement fusionner le max-age par défaut avec la valeur que l'on souhaite configurer. Dans notre cas, cela n'aurait rien changé de renvoyer directement la valeur calculée mais c'est une bonne habitude à prendre d'utiliser les méthodes de fusion des métadonnées de cache pour éviter les mauvaises surprises. La méthode mergeMaxAges() s'assure que l'on conserve toujours le max-age le plus contraignant (et c'est exactement pour cette raison que si on désactive le cache d'un bloc, toute la page est impactée).

Gérer les changements de configuration

Maintenance que la temporalité de notre cache est bien établie, il nous faut prendre en compte les changements qui pourraient venir de l'action d'une personne dans l'interface d'administration. En effet, si le titre ou une date change, par exemple, le cache du bloc devrait immédiatement être invalidé pour prendre en compte les nouvelles données. Dans le cas contraire, les gestionnaires du site n'auraient pas d'autre option que d'invalider la totalité du cache du site. Le mécanisme qui permet cette invalidation, ce sont les cache tags. La plupart des objets gérés par le cœur comme les entités de contenu ou de configuration disposent de cache tags pour les identifier mais ce n'est malheureusement pas le cas de la State API. Fort heureusement, c'est un problème très simple à contourner.

Tout d'abord, définissons un cache tag personnalisé et rattachons le à notre bloc grâce à l'implémentation de la méthode getCacheTags(). Son nom est arbitraire alors, comme souvent, nous allons le préfixer du nom du module pour éviter les collisions. Comme précédemment, nous allons utiliser une méthode pour fusionner ce nouveau cache tag avec d'éventuels autres définis par la classe parente.

  /**
   * {@inheritdoc}
   */
  public function getCacheTags() {
    return Cache::mergeTags(parent::getCacheTags(), ['hc_announcement_settings']);
  }

Ensuite, il nous faut juste modifier légèrement le formulaire d'administration de l'annonce pour lui demander d'invalider ce tag lors de l'enregistrement. Pour cela, nous avons besoin de faire appel au service cache_tags.invalidator que nous allons ajouter à notre injection de dépendances et à notre constructeur :

  /**
   * @var \Drupal\Core\State\StateInterface
   */
  protected $state;

  /**
   * @var \Drupal\Core\Cache\CacheTagsInvalidatorInterface
   */
  protected $invalidator;

  /**
   * Constructs a new AnnouncementSettingsForm object.
   *
   * @param \Drupal\Core\State\StateInterface $state
   * @param \Drupal\Core\Cache\CacheTagsInvalidatorInterface $invalidator
   */
  public function __construct(StateInterface $state, CacheTagsInvalidatorInterface $invalidator) {
    $this->state = $state;
    $this->invalidator = $invalidator;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('state'),
      $container->get('cache_tags.invalidator')
    );
  }

Ceci étant fait, il ne nous reste plus qu'à ajouter une petite ligne dans la méthode submitForm() pour provoquer l'invalidation.

$this->invalidator->invalidateTags(['hc_announcement_settings']);

Un dernier "petit" problème

Désormais, notre bloc est mis en cache suivant une logique qui s'appuie sur le mécanisme d'âge maximum pour définir quand l'expiration a lieu de façon très précise. Nous nous attendons donc à ce que le bloc apparaisse ou disparaisse approximativement au moment indiqué et ça fonctionne particulièrement bien... pour les utilisateurs authentifiés...

Le module Internal Page Cache du cœur permet de mettre en cache les pages entières à destination des anonymes afin d'améliorer drastiquement les performances. Le problème, c'est que ce cache, très agressif, ne tient pas actuellement compte des métadonnées de cache et notamment pas du max-age. En attendant que le cœur change de fonctionnement, vous pouvez contourner ce problème en installant le module Cache Control Override, qui ne nécessite aucune configuration particulière.

Conclusion

Au terme de cette paire d'articles, vous devriez y voir plus clair sur la façon de créer un formulaire et un bloc ainsi que sur la gestion du cache. Par cet exemple concret, j'espère que j'aurai réussi à vous faire visualiser des concepts qui étaient traités de façon bien plus académique dans nos précédents articles. S'il reste des zones d'ombre ou si vous voulez en savoir plus sur un point en particulier, n'hésitez pas à vous manifester dans les commentaires ci-dessous.

 

Crédit photo de couverture : Sue Cro

Catégories
Développement
Drupal
Drupal 8
Tags
state api
cache
blocs
Par Christophe MOLLET
Christophe Mollet

Comment installer Drupal 8

Cet article est un tutoriel présentant les étapes à suivre pour installer Drupal 8 sur linux. Il comprend une phase de préparation de l'environnement de travail puis les étapes de l'installation de Drupal 8.

Accessible pour tous et complet, il comprend aussi une section apportant des solutions aux erreurs couramment rencontrées lors de cette installation.

Par Artusamak
Julien Dubois

Créer un système d'annonces simple avec Drupal 8

Créer un système d'annonces simple avec Drupal 8
DuaelFr
jeu 22/11/2018 - 16:56

Développé initialement pour ce site, notre système d'annonce simple regroupe plusieurs concepts intéressants à mettre en valeur dans un article en deux parties. Ici, nous évoquerons la réflexion autour du stockage de l'information et la construction du formulaire.

Corps

Le besoin fonctionnel à l'origine de ce développement est relativement simple et se retrouve dans de nombreux projets : nous souhaitons pouvoir faire apparaître sur tout notre site un bandeau qui permettra de mettre en valeur, de façon bornée dans le temps, une information importante. Un peu d'analyse autour de cette demande nous permet de la détailler comme suit.

Une personne en charge du contenu du site doit pouvoir activer et configurer une annonce, qui apparaîtra toujours au même emplacement sur toutes les pages du site. La configuration doit permettre de choisir une date de démarrage et une date de fin d'apparition de l'annonce ainsi que son contenu.

Côté technique, la lecture de ce type de besoin soulève deux problématiques pour lesquelles il nous faudra faire preuve de vigilance :

  1. puisque cet élément est administrable, il faut qu'une interface facile d'accès et sécurisée soit mise en place ;
  2. puisque cette annonce va apparaître et disparaître sans nécessaire action humaine, il faut se méfier des problématiques liées au cache.

Saisie et stockage du contenu

En premier lieu, nous devons donc déterminer la manière dont sera stocké ce contenu car c'est de cela que découlera la façon dont il sera saisi. Plusieurs options s'offrent à nous :

  • une entité de contenu personnalisée,
  • un objet de configuration simple,
  • un bloc personnalisé,
  • un système de stockage à plat.

Choisir la bonne option

Puisque le besoin fonctionnel ne demande qu'à ce qu'une annonce soit configurée à la fois, l'utilisation d'une entité de contenu personnalisée semble un petit peu exagérée. En effet, générer une telle entité demande beaucoup de code (bien que l'on puisse utiliser un générateur pour aller plus vite) et nécessitera la création d'au moins une table dans la base de données, de nombreuses routes et contrôleurs pour l'administration. Cela aurait été tout à fait justifié s'il avait fallu pouvoir gérer plusieurs annonces à la fois mais dans notre cas cela représente trop de complexité.

Un objet de configuration simple pourrait également remplir son rôle pour le stockage mais, étant donné qu'il s'agit de permettre à la personne en charge du contenu de mettre en place cette annonce, nous ne conserverons pas cette option. En effet, nos procédures de déploiement provoquent par défaut un écrasement de la configuration de la production au profit de celle versionnée par l'équipe. Bien qu'il soit possible de préserver un ensemble d'objets de configuration lors d'un import, afin d'éviter à la personne en charge du contenu de perdre le fruit de son travail, cela nécessite d'y consacrer du temps et d'ajouter des modules au cœur. Dans le cadre de cette demande, nous avons d'autres options qui nous semblent plus judicieuses.

Un bloc personnalisé, basé sur un type de bloc spécialement conçu pour l'occasion, pourrait bien être une réponse pour sa simplicité de configuration et la mise à disposition d'une interface d'édition similaire à celle d'un nœud. Cette solution, bien que très alléchante, nous pose trois problèmes majeurs. Tout d'abord, nous n'avons pas le module Block Content actif sur notre site, ce qui signifie que nous ne l'activerions que pour un seul type de bloc qui ne contiendrait lui-même qu'un seul bloc. Deuxièmement, pour permettre à la personne en charge du contenu de modifier les champs de ce bloc, il aurait été nécessaire d'intégrer un module de la communauté supplémentaire, sinon elle aurait également pu modifier toute la configuration de tous les blocs. Enfin, la gestion très spécifique du cache dont nous avons fait mention précédemment aurait nécessité d'altérer en profondeur le fonctionnement des blocs personnalisés, ce qui nous semblait, une fois de plus, très disproportionné par rapport à la demande.

Finalement, c'est donc un système de stockage à plat, dans la State API, qui nous semble la meilleure option. En effet, le contenu de la State API est indépendant de la configuration et spécifique à l'environnement sur lequel il est défini. Son accès est très rapide et il ne nécessite aucune configuration particulière ni aucun module complémentaire. Son seul défaut par rapport aux entités de contenu personnalisées ou aux blocs personnalisés, c'est qu'il faut manuellement créer le formulaire qui permettra d'administrer l'annonce. Notez que cette option n'est viable que parce que les données que nous souhaitons stocker ne sont pas critiques pour le fonctionnement du site. Dans le cas contraire, conformément à ce qui est indiqué dans la documentation officielle, il nous aurait fallu trouver une autre solution.

Route et permissions

Entrons dans le vif du sujet ! Pour tout le code qui va suivre, il est important de noter qu'il prend place dans un module nommé hc_announce ; le namespace racine de tous les objets sera donc \Drupal\hc_announce et le nom du module sera utilisé, autant que possible, en préfixe de tous les noms machines qui pourraient entrer en collision avec d'autres modules.

En règle générale, je commence toujours par me poser la question des permissions. Dans notre cas, je souhaite pouvoir assigner le droit de modifier l'annonce indépendamment de toutes les autres permissions du site. Je vais donc créer un fichier hc_announce.permissions.yml contenant le code suivant :

administer announcement:
  title: 'Administer announcement'
  description: 'Allow to access the announcement settings form'

Ensuite, je passe à la route d'accès au formulaire, dans le fichier hc_announce.routing.yml j'ajoute l'entrée :

hc_announce.announcement_settings_form:
  path: '/admin/config/announcement'
  defaults:
    _form: '\Drupal\hc_announce\Form\AnnouncementSettingsForm'
    _title: 'Announcement settings'
  requirements:
    _permission: 'administer announcement'

Puis, comme je suis un peu perfectionniste et que je pense aux personnes en charge du contenu, j'ajoute cette route dans le menu d'administration grâce à une entrée dans le fichier hc_announce.links.menu.yml :

hc_announce.announcement_settings_form:
  title: Announcement
  parent: system.admin_config
  description: 'Announcement settings.'
  route_name: hc_announce.announcement_settings_form

Le lien "Announcement" apparaîtra donc dans le menu d'administration sous l'entrée "Configuration" matérialisée par la route parente system.admin_config.

Si vous voulez en savoir plus sur le fonctionnement des routes de Drupal 8, je vous renvoie à un ancien article issu de notre formation.

La base du formulaire

Ces actions préparatoires terminées, il est temps de passer aux choses sérieuses, le formulaire en lui même.

Il nous faut récupérer une date de début, une date de fin, un titre et un message au minimum. Pour des soucis pratiques, nous ajouterons un système pour activer ou désactiver l'annonce rapidement (c'est à dire sans avoir à jouer avec les dates). Pour clarifier l'utilisation de ce formulaire, nous n'afficherons les champs utiles que si la case à cocher pour activer l'annonce est cochée. C'est parti !

Nous créons donc le fichier src/Form/AnnouncementSettingsForm.php dans notre module avec le minimum pour que cela soit considéré comme un formulaire valide :

namespace Drupal\hc_announce\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;

/**
* Class AnnouncementSettingsForm.
*/
class AnnouncementSettingsForm extends FormBase {

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'announcement_settings_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {

    $form['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Submit'),
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $this->messenger()->addStatus($this->t('The configuration options have been saved.'));
  }

}

Le résultat n'est pas encore exceptionnel mais il nous permet de valider que la route pointe bien sur notre classe.

Capture d'écran du formulaire ne présentant qu'un bouton de validation.

L'étape suivante consiste à étoffer la méthode buildForm() pour afficher tous les champs dont nous avons besoin.

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {

    $form['enabled'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Enable announcement'),
      '#default_value' => FALSE,
    ];

    $form['announcement'] = [
      '#type' => 'details',
      '#title' => $this->t('Announcement settings'),
      '#open' => TRUE,
      '#states' => [
        'visible' => [
          ':input[name="enabled"]' => ['checked' => TRUE],
        ],
      ],
    ];
    $form['announcement']['start_date'] = [
      '#type' => 'date',
      '#title' => $this->t('Start date'),
      '#default_value' => '',
      '#required' => TRUE,
    ];
    $form['announcement']['end_date'] = [
      '#type' => 'date',
      '#title' => $this->t('End date'),
      '#default_value' => '',
      '#required' => TRUE,
    ];
    $form['announcement']['title'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Announcement title'),
      '#default_value' => '',
      '#maxlength' => 64,
      '#size' => 64,
    ];
    $form['announcement']['announcement'] = [
      '#type' => 'text_format',
      '#title' => $this->t('Announcement'),
      '#default_value' => '',
      '#required' => TRUE,
      '#format' => 'full_html',
    ];
    $form['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Submit'),
    ];

    return $form;
  }

Ce qui nous donne un résultat déjà plus proche de nos besoins.

Capture d'écran du formulaire présentant tous les champs définis par le code : activation de l'annonce, date de début, de fin, titre et contenu.

Validation de la saisie

La magie de Drupal fait que les champs marqués comme required seront validés automatiquement, de même que les données relatives aux types de champs auront leur format vérifié avant soumission. Il ne nous reste qu'à vérifier que la date de fin est bien postérieure à la date de début et nous allons pour cela implémenter la méthode validateForm().

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
    $values = $form_state->getValues();
    if ($values['end_date'] < $values['start_date']) {
      $form_state->setErrorByName('end_date', $this->t('The ending date must be greater or equal than the starting date.'));
    }
  }

Le résultat avec le module du cœur Inline Form Error actif (vous devriez activer ce module sur tous vos projets par défaut) est plutôt sympa.

Champ date de fin en erreur indiquant que sa valeur doit être supérieur ou égale à la date de début.

Enregistrement et injection de dépendances

Pour finir, il va nous falloir enregistrer l'information dans la State API et nous assurer que le formulaire tiendra compte des données existantes lors de son prochain affichage. Contrairement aux formulaires de configuration qui proposent un ensemble de méthodes pour accéder aux objets de configuration, nous ne disposons d'aucune aide pour accéder à la State API. Pour y parvenir, nous pourrions faire appel directement à l'objet \Drupal qui contient toutes les méthodes d'assistance nécessaires mais, puisque nous aimons le travail bien fait et le respect des bonnes pratiques, mais aussi dans l'intérêt de l'exercice, nous allons faire appel à l'injection de dépendances.

Dans le cas d'un formulaire qui étend la classe FormBase, nous n'avons pas besoin de spécifier que nous souhaitons implémenter l'interface ContainerInjectionInterface car c'est déjà fait dans la hiérarchie de classe. Il nous suffit donc d'implémenter la méthode statique create() et de spécifier le constructeur de notre objet.

namespace Drupal\hc_announce\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\State\StateInterface;

/**
* Class AnnouncementSettingsForm.
*/
class AnnouncementSettingsForm extends FormBase {

  /**
   * @var \Drupal\Core\State\StateInterface
   */
  protected $state;

  /**
   * Constructs a new AnnouncementSettingsForm object.
   *
   * @param \Drupal\Core\State\StateInterface $state
   */
  public function __construct(StateInterface $state) {
    $this->state = $state;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('state')
    );
  }

// [...]

Le service de construction de formulaire, sachant que notre classe implémente ContainerInjectionInterface, instanciera notre objet par l'intermédiaire de sa méthode create(), en lui fournissant le conteneur de services en paramètres. C'est cette méthode qui créera l'instance du formulaire à proprement parler en lui fournissant les services dont elle a besoin pour fonctionner, dans notre cas, la State API.

Maintenant qu'on a notre service à disposition, rien n'est plus simple que de stocker les données saisies. Il nous faut juste un peu enrichir la méthode submitForm().

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $values = $form_state->getValues();

    $this->state->set('hc_announcement', [
      'enabled' => $values['enabled'],
      'start_date' => $values['start_date'],
      'end_date' => $values['end_date'],
      'title' => $values['title'],
      'announcement' => $values['announcement'],
    ]);

    $this->messenger()->addStatus($this->t('The configuration options have been saved.'));
  }

En faisant le choix de ne pas filtrer les données saisies, notamment pour le titre qui est un champ texte simple, nous gardons en tête qu'il faudra être vigilants lors de leur affichage. Heureusement, Twig est là pour nous aider à éviter les failles XSS ! Nous y reviendrons dans la seconde partie de cette série.

La dernière chose à faire est d'enrichir la méthode buildForm() pour afficher les données enregistrées dans la State API lors de l'affichage du formulaire. Je vous épargne la totalité du code pour vous montrer uniquement l'exemple sur le champ "enabled" :

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $config = $this->state->get('hc_announcement');

    $form['enabled'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Enable announcement'),
      '#default_value' => !empty($config['enabled']) ? $config['enabled'] : FALSE,
    ];

// [...]

Lorsque vous repasserez sur tous les champs pour utiliser les valeurs stockées, n'oubliez pas le #format du champ "announcement".

Et voilà le travail !

Formulaire de configuration de l'annonce complet affichant tous les champs ainsi que leurs données actuelles.

 

Voilà déjà une bonne chose de faîte ! Dans la prochaine partie de cet article, nous aborderons l'affichage de ces données en front et la gestion du cache.

À très bientôt !

 

Crédit photo de couverture : Sue Cro

Catégories
Développement
Drupal
Drupal 8
Tags
state api
formulaires
configuration
entités
Par Artusamak
Julien Dubois

Installer Drupal depuis la configuration

Installer Drupal depuis la configuration
DuaelFr
jeu 15/11/2018 - 09:30

Depuis Drupal 8.6.0 il est possible d'installer un site depuis un ensemble de fichiers de configuration, voyons comment cela fonctionne.

Corps

Depuis la sortie de Drupal 8 et de son système de gestion de la configuration, la communauté n'a cessé de demander à ce qu'il soit possible de procéder à une installation complète à partir d'un jeu de fichiers de configuration existant. Il aura fallu plus de deux ans et des efforts considérables de dizaines de contributeurs et contributrices pour rendre cela possible.

Utilité

Cette nouvelle fonctionnalité, jusqu'à présent accessible avec un peu de bricolage grâce au profil d'installation Configuration Installer, ouvre de nombreuses possibilités. Tout d'abord, il y a les agences qui souhaiteraient avoir un socle pour démarrer rapidement leurs projets (c'est notre cas), mais aussi les développeurs et développeuses qui veulent pouvoir expérimenter des choses tout en étant capables de reconstruire rapidement leur environnement si besoin ou de monter des environnements de test à la volée. Côté fonctionnel cela rend également plus simple le clonage de site sans avoir à nettoyer les contenus et cela permet également, dans certains cas comme pour un système d'usine à sites, de disposer d'un socle minimal de configuration disponible lors de la création d'un nouveau site.

Préparation

Comme vous vous en doutez, la première étape est d'avoir un jeu de fichiers de configuration disponible. Si ce n'est pas votre cas, faîtes une installation classique avec le profil d'installation minimal, activez quelques modules, changez quelques options dans l'administration du site, puis exportez la configuration via le backoffice (chemin : admin/config/development/configuration/full/export) ou via Drush (drush config:export).

Placez vos fichiers de configuration dans un répertoire prévisible, hors de votre DocumentRoot si possible. Par exemple, si vous suivez l'organisation proposée par le drupal-project, cela se fera dans un répertoire config/sync à la racine du projet. Puis, indiquez l'emplacement de cette configuration dans votre fichier settings.php (ou settings.local.php si vous en avez un) de façon relative à la racine de Drupal, c'est à dire à l'emplacement du fichier index.php. Par exemple :

$config_directories[CONFIG_SYNC_DIRECTORY] = '../config/sync';

Note : il est aussi possible de stocker cette configuration dans le répertoire config/sync de votre profil d'installation sans avoir besoin de modifier le fichier de settings. Cela peut être très utile dans le cadre d'une distribution (interne ou contribuée) mais, dans la plupart des cas, un répertoire indépendant sera préférable car il permettra de maintenir la configuration à jour plus simplement au fil du projet.

Utilisation

Une fois votre référentiel de configuration et vos fichiers prêts, vous n'avez plus qu'à installer votre site.

C'est possible de réaliser cette opération depuis l'interface graphique fournie par Drupal, comme illustré ci-dessous.

Écran d'installation de Drupal faisant apparaître l'option "Use existing configuration" qui permet d'installer le site en se basant sur la configuration existante.

Cela est également possible via Drush 9.4 ou supérieur grâce à l'option --existing-config de la commande drush site:install.

Limitations et dépannage

Attention ! À l'heure actuelle, cette fonctionnalité ne fonctionne pas avec les profils d'installation qui implémentent un hook_install. C'est pour cette raison que je vous ai conseillé de tester en utilisant le profil minimal. Cela sera sans doute amené à changer dans le futur puisque la communauté travaille actuellement sur cette problématique.

De plus, si vous décidez de créer votre propre profil d'installation (ce que je recommande chaleureusement, j'en parlerai dans un futur billet), faîtes bien attention à l'export du fichier core.extension.yml. En effet, celui-ci contient la liste de tous les modules activés, y compris votre profil qui est considéré comme un module, ainsi qu'une référence directe au profil avec lequel le site a été installé. Si vous avez procédé à une installation via le profil minimal, il faudra remplacer ce dernier dans le fichier par le nom machine de votre propre profil sous les clefs "module" et "profile". Si vous ne faîtes pas cette modification, l'installation échouera.

Extrait d'un différentiel de code illustrant le changement de profil dans le fichier core.extension.yml.

Et voilà ! Vous savez tout. Si vous tombez sur des cas étranges, n'hésitez pas à nous laisser un petit commentaire !

 

Crédit photo de couverture : Sally Wilson

Catégories
Développement
Drupal
Drupal 8
Tags
configuration management
profil d'installation
Par Christophe MOLLET
Christophe Mollet

Retour sur le Meetup Drupal

Le meetup

Tout d’abord, je tiens à remercier l’ensemble des participants de s’être déplacé pour notre premier meetup drupal. Grâce à vous la communauté ne fait que s’agrandir.

Pour ceux qui auraient loupé ce Meetup voici un petit résumé.

Par admin

Sprint de traduction de la documentation à Montpellier !

Nous nous sommes retrouvés à huit, dès 9h30 ce samedi matin, dans les locaux de Smile à Montpellier.
Après avoir mené plusieurs discussions à bâton rompu sur des sujets très divers, qui tournaient souvent autour de la contribution, nous nous sommes attelés, en début d'après-midi, à celle qui nous est apparu comme la plus nécessaire : la traduction de la documentation Drupal 8. 
Nous avons donc fait un point sur les travaux en cours sur :

et sommes parvenus à traduire 7 issues (sur environ 150) ...

En parrallèle, 

  • Un atelier s'est tenu sur le thème "découverte du site building (structure, entités, contribution)", avec une présentation de Julien,
  • Nous avons échangé autour de thèmes très larges tel que, en vrac, les méthodes agiles, la démocratie liquide, les cycles de vie des modules, la vie en entreprise, le télétravail, les missions de l'association, le prochain Drupal Camp, Drush et Composer, les ressources serveur, le thème du prochain Meetup,

Nous n'avons pas consommé l'ensemble des victuailles, mais nous y sommes employés ...

Nous avons fixé la date du prochain meetup Drupal Montpellier au 14 Novembre.

Et nous sommes quittés regonflés et satisfaits ...

En page d'accueil : 
Version de Drupal : 
Par flocondetoile
Adhérent

Surcharger une configuration de façon dynamique avec Drupal 8

Dans certains cas de figure, il peut être extrêmement intéressant de pouvoir surcharger une configuration de façon dynamique. Un des premiers cas d'usage immédiatement perceptible est dans le cas d'une usine à sites disposant d'un ensemble de fonctionnalités partagées et déployées, et donc de configurations identiques partagées.

Par ftorregrosa
Adhérent
Florent Torregrosa

Résumé de Drupal Europe 2018

Du 10 au 14 septembre 2018 a eu lieu Drupal Europe. L'événement Drupal européen organisé par la communauté, remplaçant la DrupalCon cette année.

Nous étions autour de 1000 participants sur 5 jours.

Sprints

Entity share

J'ai pu consacré du temps pour mettre à jour les issues du module Entity share :

Tags: 
Par flocondetoile
Adhérent

Un exemple de cache en action avec Drupal 8

Comme on dit en matière de programmation informatique, seules deux choses sont extrêmement complexes : le nommage des variables et l'invalidation du cache. Drupal 8 dispose d'un système de cache automatique activée par défaut proprement révolutionnaire qui permet de proposer un cache pour les visiteurs anonymes et aussi surtout pour des utilisateurs authentifiés et ceci sans aucune configuration. Mais le propos de ce billet n'est pas de rentrer dans le détail de ce système de cache, mais plutôt d'illustrer l'utilisation de la cache API permettant de mettre en place son propre cache pour un cas d'usage bien précis.

Par Artusamak
Julien Dubois

Driesnote – State of Drupal – Drupal Europe 2018

Comme régulièrement, voici un mini transcript de la keynote de Dries pour Drupal Europe 2018 visant à raconter l’état de l’art de Drupal.

Pourquoi sommes nous ici ? Car nous avons envie de construire un Drupal que les gens et nous aimons.

« Impact gives purpose »

L’impact de Drupal dans le monde réel, aide à se motiver et se rappeler dans les moments difficiles qu’on a un impact concret lorsque l’on se prend la tête avec les issues.

Il y a un plan pour y arriver : promouvoir Drupal, améliorer drupal pour les créateurs de contenu, les développeurs, les nouveaux venus. Chaque piste a des étapes intermédiaires. Et cela fonctionne !

I) State of Drupal

8.6.0 a été publié la semaine dernière… comme prévu ! Ce qui est nouveau depuis Drupal 8 mais toujours rassurant et efficace pour rassurer tout le monde.

Il y a de plus en plus de contributeurs et de modules stables sur la dernière année et surtout des actifs dans les initiatives du cœur.

12 initiatives officielles ont lieu en parallèle (est-ce trop ?). Voici un récap sur ces initiatives.

A/ Améliorer Drupal pour les créateurs de contenu

Se satisfaire de copier du texte depuis Word rendu à peu près normalement dans le contenu ne suffit plus. Les contributeurs passent plus de temps sur l’interface qu’avant.

Démo des initiatives : Layout, media, out of the box, workflow. (Contenu de la démo : édition de contenu en ligne, mise en page par article, utilisation du site de démo Umami, préparation de contenu pour mise en ligne plus tard (staging de contenu).

[ndr : C’est vraiment impressionnant comparé à ce que l’on avait il y a 2 ou 3 ans !]

B/ Améliorer Drupal pour les développeurs

Initiatives : Admin UI, API-first, Javascript modernisation

1 an s’est écoulé depuis le début de l’initiative sur la modernisation du JS. Les objectifs étaient d’améliorer l’expérience d’admin, moderniser les API internes et le JS, tisser plus de liens avec la communauté Javascript.

La communauté s’appuie maintenant sur des tests utilisateurs pour avoir une idée plus fiable des fonctionnalités sur lesquelles travailler et qui sont attendues par les utilisateurs.

Un rafraîchissement du thème d’admin est en cours pour redonner un coup de frais à l’admin en attendant le travail de fond sur la refonte complète de l’expérience d’admin.

Drupal va s’appuyer sur React-UI pour sa nouvelle expérience d’administration (et seulement son administration). Twig ou un autre framework JS peut et pourra toujours être utilisé en front.
Pour réussir, le module contrib JSON API est utilisé (il s’agit de l’initiative API-First) en attendant que le module soit mature pour intégrer le cœur.
L’équipe s’appuie sur un prototype pour faire la démo du projet, on peut y voir des formulaires plus réactifs, une expérience bien plus dynamique et fluide.
Ce travail a aussi permis de faire du nettoyage dans le code JS existant.

C/ Améliorer Drupal pour les nouveaux venus

Il y a 6 mois, une critique a été formulée sur le temps d’installation de Drupal pour un nouveau venu (plus de 20 clics et 15 minutes pour installer Drupal).
Le profil d’installation Umami permet d’avoir un site avec du contenu dès leur première installation pour expérimenter Drupal. Un gros travail d’amélioration de la documentation est en cours sur drupal.org.
La page de téléchargement de Drupal a été améliorée en ajoutant des liens pour apprendre à installer Drupal et le tester et en simplifiant des commandes.
Grâce à cela, 3 clics et 1 minute 20 suffisent maintenant pour avoir un Drupal testable !

D/ Améliorer Drupal pour les développeurs

Initiatives : Automatic updates, migrate, composer œ core, config management 2.0, security LTS.

Beaucoup de progrès, trop pour en parler correctement. Des billets de Dries suivront.

Gros plan sur Security LTS. Jusqu’à maintenant, les équipes ont 1 mois pour mettre à jour Drupal avant qu’une branche majeure ne soit plus maintenue.  (Lors de la sortie de 8.5.x, 8.4.x était maintenue pour un mois avant d’être dépréciée). Avec la sortie de Drupal 8.6.x, la version précédente sera maintenue 6 mois. La durée de vie d’une version majeure sera donc d’un an (6 mois de vie active + 6 mois supportés par l’équipe de sécurité) contre 7 mois précédemment.

Les prochaines étapes pour les initiatives actuelles
Les prochaines étapes pour les initiatives actuelles

E/ Promouvoir Drupal

L’équipe va avancer malgré le fait que 78k des 100k$ aient été levés pour faire la promotion de Drupal. Le première action a été la publication d’un communiqué de presse pour la sortie de la 8.6.0. Préparation d’une plaquette, de références et d’espace de collaboration en cours de travail.

Drupal 7, 8 et 9.

Drupal 8 a des dépendances externes. Symfony 3 sera déprécié en novembre 2021. La migration vers une nouvelle version de Symfony devra se faire en passant à Drupal 9 pour des raisons de rétro-compatibilité. Drupal 8 devrait donc être en fin de vie en novembre 2021. L’objectif est de laisser un an aux mainteneurs pour passer de Drupal 8 à Drupal 9. Un an est une durée courte mais la politique de gestion des versions a été modifiée pour simplifier ces transitions. Il faut un an pour préparer Drupal 9. Drupal 9 serait donc prévu pour 2020. Drupal 8.7.0 et 8.9.0 existeront pour sûr.
Fin de vie pour Drupal 7 en 2020 en théorie mais prolongé jusqu’à novembre 2021. Drupal LTS sera toujours présent pour 7 comme il existe pour 6.

d9

Drupal.org bascule sur Gitlab

Réduction de la barrière à l’entrée pour les contributeurs en passant à des contributions à base de pull requests plutôt que de patches. Ce changement sera majeur et vraiment une excellente nouvelle pour la communauté.

L’intégration va se dérouler en 3 temps :

  1. Phase 1 : Q4 2018 / bascule des dépôts Git vers Gitlab + revue de code via Gitlab
  2. Phase 2 : Q1-Q2 2019 / merge requests et édition de code en ligne (via le navigateur)
  3. Phase 3 : Un jour / Fonctionnalités complémentaires (graphs, CI/CD…)

Annonces complètes :

Et dernière info…

Il y aura une DrupalCon en Europe en 2019 et elle aura lieu à Amsterdam du 28 octobre au 1er novembre !

 

Par Christophe MOLLET
Christophe Mollet

Meetup Drupal à Paris

Nous avons remarqué qu’à l’exception du Drupalcamp 2019 qui revient à Paris en février et du dernier Drupagora de juin, il manque un meetup pour échanger, dans un cadre informel, sur les dernières évolutions de Drupal.

C’est pourquoi je vous propose un meetup en octobre prochain à Paris.

Par admin

Drupal 8.6.0 est disponible !

Washington D.C., le 5 Septembre 2018 - La communauté Drupal vient d’annoncer une mise à niveau majeure de Drupal 8. Cette mise à niveau offre une meilleure expérience, faisant de son utilisateur un héros au travail. De l'installation simplifiée et des mises à niveau plus stables pour les équipes techniques jusqu’à l'amélioration de l'expérience utilisateur pour les équipes marketing et de rédaction, Drupal 8.6.0 apporte des améliorations significatives par rapport à toutes les versions antérieures de Drupal.

Une nouvelle démonstration est incluse dans cette version afin d’inspirer les créateurs de sites par des exemples à l’état de l’art. De plus, les équipes marketing peuvent facilement publier du contenu complexe à l’aide des nouvelles fonctionnalités de l’éditeur de contenu, notamment: une meilleure prise en charge des vidéos, une nouvelle bibliothèque multimédia, et une notion d’espaces de travail qui permet des circuits de validation avancés. Comme pour toute mise à jour fonctionnelles majeures, les utilisateurs découvriront également de nombreuses corrections et améliorations globales.

Megan Sanicki, directrice exécutive de la Drupal Association, a déclaré: “Drupal 8.6 est une mise à jour importante en raison de l’accent mis sur la facilité d'utilisation. Cette version renforce l'expérience utilisateur, facilitant ainsi la migration à partir d'anciennes versions, sa mise en œuvre, mais également la capacité des équipes marketing à obtenir plus rapidement des résultats significatifs. Avec une communauté fortement mobilisée qui se concentre sur la réalisation de fonctionnalités qui valorisent les utilisateurs, je suis ravi de cette version et de ce qui est à l'horizon pour Drupal.”

Alors, quoi de neuf dans Drupal 8.6.0?

Un des formidables aspects de Drupal 8.6.0 est que la prise en charge de la migration est grandement améliorée et cela facilite la migration de Drupal 6 et 7 vers Drupal 8. Dans cette version les modules Drupal “Migrate” (migration depuis les précédentes versions majeures de Drupal) et “Migrate UI” (interface utilisateur de mise à niveau) fournissent une solution pour mettre à jour les sites plus anciens. Cela signifie que si vous avez un site monolingue en Drupal 6 ou 7, vous pouvez désormais utiliser une interface utilisateur officielle et intégrée pour migrer votre site vers Drupal 8. Les migrations multilingues similaires sont encore expérimentales mais maintenant intégrées au module “Migrate Drupal Multilingual”.

Autre nouveauté de cette version, l’intégration stable de la prise en charge de médias distants, préconfigurée pour les vidéos YouTube et Vimeo. De plus, dans un nouveau module expérimental, vous pouvez désormais parcourir les médias existants et en ajouter de nouveaux en utilisant un widget dédié. La médiathèque peut être personnalisée en fonction des besoins de l’utilisateur.

Les fonctionnalités “layout” (gestion des gabarits) de Drupal 8.6.0 sont nettement améliorées. Le module expérimental “Layout Builder” est une avancée enthousiasmante pour les créateurs de sites car il prend en charge la personnalisation en fonction des affichages (par exemple: mode complet ou résultats de recherche). Plutôt que d'être limités par des champs empilés les uns en dessous des autres, les utilisateurs peuvent créer des gabarits avec des sections dynamiques, créant ainsi davantage d'opportunités pour des mises en page personnalisées. Il est également possible maintenant d'ajouter du contenu propre à un gabarit spécifique. Ceci est utile pour des éléments tels qu’une promotion qui ne doit être visible que dans une seule landing page.

Drupal 8.6.0 propose également un nouveau profil de démonstration et un nouveau thème dans son processus d’installation. Ceci est particulièrement intéressant pour les personnes qui veulent évaluer le CMS et les agences de développement car il offre un moyen plus facile de voir ce qui est possible avec Drupal 8. La démonstration “magazine de cuisine”, Umami, est une belle et moderne démonstration des capacités de Drupal, qui utilise un site imaginaire dédié à la nourriture pour présenter sa puissance en termes de modèle de données, de remontée de contenus, de gestion des gabarits et de modération. Des utilisateurs tests sont créés, avec des profils auteurs et éditeurs de magazines, pour expérimenter différents aspects de l’utilisation de l’interface de gestion de contenu de Drupal.

Tiffany Farriss, CEO de l'agence digitale Palantir.net, déclare: “Drupal dispose de puissantes capacités. Pendant trop longtemps, celles-ci ont été cachées dans les coulisses, où seuls les utilisateurs expérimentés ou techniques pouvaient en faire l'expérience. Nous sommes ravis d'avoir maintenant Umami, pour montrer, dès son installation, la force et le potentiel de Drupal aux utilisateurs techniques et fonctionnels.”

Drupal 8.6.0 propose également un nouveau module expérimental dédié aux espaces de travail qui sont essentiels lorsqu’il faut valider de grandes quantités de contenu. Les fonctionnalités existantes de modération de contenu étaient idéales lorsque vous deviez faire passer à des éléments de contenu individuels un circuit de modification et de validation. Le nouveau module expérimental “Workspaces” permettra de valider des lots de contenu en une seule fois, avec la possibilité de définir plusieurs espaces de travail, d'y apporter des modifications et d’effectuer des déploiements de l’un à l’autre avec une interface utilisateur intuitive.

Consciente de la nécessité de communications ultra-rapides au sein de son organisation, Alimentation Couche-Tard a consolidé plusieurs de ses systèmes historiques pour créer un seul intranet mondial permettant de connecter ses effectifs. Appelé “Inner Circle”, le nouvel intranet fournit une plate-forme puissante pour partager des informations et gérer les opérations dans toute l'entreprise, tout en créant des synergies et des gains d'efficacité à l'échelle de l'organisation pour plus de 100 000 employés. Il tire parti des capacités de création de contenu, de gestion des cycles de vie documentaires et de multilinguisme de Drupal 8 pour créer un forum à la fois super-local et super-mondial.
“Couche-Tard peut agréger toutes les connaissances, le contenu et les ressources de l'organisation en un seul endroit, puis les filtrer pour offrir une expérience hautement personnalisée à chaque employé ou intervenant, en fonction de son rôle, de sa localisation et de sa langue”, a déclaré Marie- Noëlle Cano, directrice senior des communications globales chez Alimentation Couche-Tard. "Couche-Tard a amélioré le périmètre, la vitesse et la densité de sa communication interne avec Drupal 8 tout en réduisant les coûts.”

La communauté Drupal a travaillé dur pour faciliter considérablement la mise à disposition d’un environnement d’évaluation ou de développement; les nombreuses améliorations techniques permettent une installation rapide qui aboutit à l’ouverture d’une plateforme prête à l'emploi dans le navigateur. Le programme d'installation reconnaît désormais également une configuration existante et fournit une option permettant de reconstruire facilement un site à partir de cette configuration existante, en extrayant le contenu du cloud plutôt que d'exiger que le contenu soit stocké localement.

“Cette mise à jour est pleine de nouvelles fonctionnalités fascinantes qui montrent que Drupal est la plate-forme incontournable pour des expériences digitales ambitieuses. Au nom de la Drupal Association et de la communauté Drupal, je souhaite remercier tous ceux qui ont contribué à Drupal 8.6.0”, a déclaré Sanicki.

À propos de Drupal
Drupal est un logiciel de gestion de contenu. Il est utilisé pour créer de nombreux sites et applications Web que vous utilisez chaque jour. Drupal dispose d'excellentes fonctionnalités standard, d'une gestion de contenu simple, de performances fiables et d'une excellente sécurité. Ce qui le distingue, c'est sa flexibilité; la modularité est l'un de ses principes fondamentaux. Ses outils vous aident à créer le contenu polyvalent et structuré dont les expériences Web ambitieuses ont besoin.

À propos de la Drupal Association
La Drupal Association se consacre à la promotion et au soutien du projet Drupal, de sa communauté et de sa croissance. La Drupal Association aide la communauté Drupal en matière de financement, d'infrastructure, de formation, de promotion, de distribution et de collaboration en ligne sur Drupal.org.

#

Plus d’informations sur Drupal 8.6.0
Tim Lehnen, Director of Engineering, Drupal Association: tim@association.drupal.org

En page d'accueil : 
Version de Drupal : 
Par flocondetoile
Adhérent

Ajouter des résultats à une recherche effectuée avec Search API et ElasticSearch sur Drupal 8

Lors de recherches effectuées sur les contenus d'un site Drupal 8, il peut parfois être utile de pouvoir rajouter certains contenus aux résultats déjà obtenus, et ceci en fonction de ces résultats. Cela peut être du contenu qu'on souhaite mettre en avant quelque soit la recherche, ou faire remonter des landing page génériques qui servent et complètent les contenus trouvés ou encore les auteurs des contenus issus des résultats de la recherche.

Par Christophe MOLLET
Christophe Mollet

Drupal 8

Drupal 8 vient d'être enfin dévoilé. Découvrez toutes les nouveautés de cette nouvelle version.

Par Christophe MOLLET
Christophe Mollet

Drupal

Vous souhaitez prendre connaissance des raisons pour lesquelles Drupal est recommandé par sa communauté ?

Par Christophe MOLLET
Christophe Mollet

Drupal Camp

La Drupal Camp est une occasion d'apprendre, partager ses idées et de rencontrer les différents acteurs de la communauté Drupal. Vous souhaitez connaître les dates ?

Pages