Planète

Par kgaut
Kevin Gautreau

Drupal 8 & Drupal 9 - supprimer de la config depuis le code

Voici comment, via un script où une fonction d'update, supprimer des clés de configuration dans la base de données :

<?php

$configsToDelete = [
  'mon_module.ma_config',
  'mon_module.mon_autre_config',
];

foreach ($configsToDelete as $configToDelete) {*
  Drupal::configFactory()->getEditable($configToDelete)->delete();
}

 

Par Artusamak
Julien Dubois

Évolution ou refonte complète de votre site internet ?

Évolution ou refonte complète de votre site internet ?
stephanie@happyculture.coop
lun 11/04/2022 - 16:06

Pour que votre site internet suive les changements dans les technologies web, les tendances en webdesign et propose la meilleure expérience utilisateur possible, vous pouvez soit le faire évoluer soit procéder à une refonte complète. Décryptons ensemble les solutions.







Corps

Entre l’évolution des technologies web et les tendances du webdesign, votre site internet doit rester à jour et suivre les évolutions techniques.
Une fois mis en ligne, vous l’enrichissez régulièrement de nouveaux contenus. Seulement voilà, au bout de quelques années, votre site peut ne plus correspondre exactement à l’image de votre structure, il vieillit, il peut devenir capricieux techniquement… sachant que l'obsolescence d’un site peut avoir un impact négatif sur votre image de marque et votre activité (design/ergonomie dépassée, baisse des performances économiques, mise à jour du contenu complexe).
Pas mal de raisons qui vous font dire que le changement, c’est maintenant !
Oui mais voilà, qu’est-ce qu’on change ?

Vous avez le choix entre 3 options selon l’étendue des “dégâts” :

  • l’évolution graphique 
  • l’évolution technique
  • la refonte complète

Avant de décider de l’option idéale, vous pouvez étudier les avis clients/prospects qui le visitent, prendre en compte le ressenti des équipes qui utilisent tous les jours le site et lister les problématiques rencontrées, voir ce que font les concurrents etc. Mais surtout vérifiez les statistiques et la performance de votre site. Et demandez-vous aussi ce que vous attendez de lui au regard des objectifs qui l’avaient vu naître.

1/ L’évolution graphique pour une modernisation

Si vous souhaitez remettre au goût du jour la perception visuelle de votre site, vous pouvez faire des petits pas ou décider de totalement repeindre le site.
Si votre site semble daté, vieillot, qu’il ne répond plus aux nouvelles tendances de design, il est temps de lui offrir un lifting. 
Dans une évolution graphique, vous n’allez pas changer la structure, l’architecture générale de votre site. Vous gardez le socle en l’état et modifiez la partie front end ou visible de votre site. 

Actualisez vos images et visuels

N'hésitez pas à remettre au goût du jour vos visuels et à remplacer les images par de nouvelles plus actuelles. Il existe de nombreuses plateformes d’images gratuites et libres de droits. Pensez à garder un œil sur le poids de vos pages pour limiter l’obésité croissante des pages web au fil du temps.

Votre identité visuelle évolue

Si votre identité visuelle évolue, vous allez alors mettre votre site aux couleurs de cette nouvelle charte graphique et intégrer votre nouveau logo, vos boutons et icônes, ou encore la typographie.
Vous pouvez également vouloir simplement moderniser ou rafraîchir la perception du site pour coller à l’air du temps sans tout changer.

Vous réorganisez le contenu

Le design doit être complètement repensé car la circulation dans les contenus n’est pas fluide ou les utilisateurs peinent à trouver ce qu’ils cherchent suite aux conclusions d’un audit en ergonomie par exemple.
Dans ce cas, les travaux seront plus imposants mais vous pourrez capitaliser sur le contenu existant, qui lui reste pertinent. Seule sa présentation et ce qui l’entoure sont retravaillés.

Un site responsive

Aujourd’hui tous les sites internet se doivent d’être responsive, accessible et lisible sur tous les supports, notamment sur les mobiles car 82% des Français se connectent à Internet depuis un mobile. Vous devez adapter votre contenu pour être lisible sur plusieurs largeurs d’écran différentes et optimiser l’espace disponible à l’écran.

2/ L’évolution technique pour augmenter l’impact

Une mise à jour technique peut être nécessaire dans plusieurs cas. 

Optimisez la vitesse de chargement de votre site web

Votre site est-il lent à charger ? Devenue essentiel dans la réussite d’un site internet, la vitesse de chargement a un impact sur la réussite de votre site. Les internautes patientent seulement 3 secondes pour arriver sur votre site. Si dans ce laps de temps, votre site ne s’affiche pas, ils surferont sur des sites concurrents. Travaillez sur le poids des pages, l’utilisation de différents niveaux de cache, le chargement progressif… Faites maigrir votre site.

Il existe des outils pour vérifier la vitesse de chargement de votre site. Notez que la vitesse de chargement sert également votre SEO et votre classement sur Google. 

Migration de votre CMS vers une version plus récente 

Votre CMS a peut-être besoin de passer la vitesse supérieure. On parle ici de montée de version. Jusqu’à novembre 2015, si vous passiez d’une version majeure à une autre de Drupal (exemple de Drupal 7 à Drupal 8), vous étiez obligés de passer par une refonte de votre site pour réappliquer votre code métier et votre contenu à la nouvelle version. Suite aux critiques des agences et autres acteurs de l’écosystème Drupal sur l’importance de l’effort à produire pour y arriver, la communauté a fait évoluer cette logique pour permettre de facilement passer d’une version majeure à une autre (ex : Drupal 8 à Drupal 9). 
Faire une montée de version vous permet de bénéficier des nouvelles fonctionnalités, APIs, optimisations de performances ou refontes d’interfaces.
Le fonctionnement de cette industrie fait que vous devriez toujours chercher à être au plus proche des dernières versions disponibles. 
Si votre site est dit headless, il est possible de modifier le backoffice sans faire évoluer le front-office.
> Notre article sur la fin de vie de Drupal 7 et 8 pourrait aussi vous intéresser.

3/ Repartir d’une feuille blanche

On parle de refonte complète lorsque des modifications en profondeur sont nécessaires et que faire évoluer l’existant sera plus complexe que tout reprendre.

Plusieurs raisons peuvent être à l’origine d’une refonte complète, comme par exemple : 

  • La structure de votre site ne répond pas aux attentes de vos utilisateurs et par conséquent ne répond pas à vos objectifs
  • Votre activité évolue et nécessite le développement de nouvelles fonctionnalités (Le rôle/positionnement du site doit changer suite à des décisions internes)
  • Vous n’avez pas la main sur votre contenu (un prestataire qui vous a enfermé dans un outil propriétaire ) ou 
  • Votre site est difficile à administrer (départ des personnes clés du projet et perte de la compréhension du fonctionnement)
  • Votre DSI vous impose un changement de technologie (changement de CMS ou framework). Changer de CMS implique souvent une refonte car il s'agit d’une migration du back et du front.

Une refonte offre alors plus de possibilités et vous permet d’avoir un site tout neuf et sur-mesure ! 

Mais attention, une refonte ne se fait pas à la légère. Elle doit être bien pensée en amont car elle demande un certain investissement. 

D’abord, c’est un investissement de temps : comptez plusieurs semaines voire plusieurs mois pour un projet de refonte. Ce projet transversal va aussi mobiliser les ressources internes des différents services impliqués dans le site web, ce qui augmentera les chances de réussite de la refonte. Et selon la taille du projet, une personne peut être entièrement dédiée en tant que Chef de projet de la refonte.

Et, c’est aussi un investissement financier : si vous faites appel à une société externe ou un indépendant pour vous aider dans votre chantier de refonte, cela impliquera un budget plus ou moins conséquent selon les travaux que vous souhaiterez leur confier. Selon la maturité de votre projet, une aide externe peut vous aider à capter les besoins de vos utilisateurs ou de votre équipe interne et vous aider dans la rédaction et le cadrage de votre expression des besoins (Happyculture, par exemple !)

Donc avant de vous lancer, vous allez devoir analyser votre site et ses performances, définir vos nouveaux objectifs, lister les problématiques rencontrées, etc, tout ce qui vous servira pour rédiger une bonne expression de besoins avant de contacter l’agence web qui réalisera cette prestation.
On profitera de l’occasion pour s’interroger sur les contenus existants. Faut-il tout conserver ? Tout réécrire ?

Vous devez avoir un cap clair avec vos objectifs de refonte car tout au long de ce projet, ils vous aideront à faire des arbitrages et juger à la fin de la mission si la refonte est une réussite.

Nous serons ravis de répondre à vos questions et de vous accompagner dans votre projet de refonte ou pour vous aider à définir vos objectifs. N’hésitez pas à nous contacter.

=> Et pour allez plus loin, consultez notre guide pour la refonte de votre site (bientôt en ligne).

Enfin, n'hésitez pas à jeter un œil à ce petit musée du web qui montre les changements parfois radicaux de sites web bien connus. 

Pour conclure, la mise en ligne de votre site n’est que le début d’une belle histoire. Pour que votre site reste en phase avec vos objectifs, gardez à l’esprit que la vie d’un site ne s’arrête pas à sa mise en ligne initiale, faites-le évoluer sur la durée et apportez-lui des améliorations régulières. Vous pérenniserez alors les développements effectués, optimiserez les performances de votre site et éviterez une refonte complète à court terme. L’écologie est au centre de bien des préoccupations. Nous devons aussi prendre notre part dans la création de sites. Rallonger la durée de vie des sites doit (re)devenir une préoccupation plutôt que d’entretenir la course au changement permanent. 
 

Crédits : photo de David Zieglgänsberger - Unsplash

Catégories
Développement
Drupal
Tags
refonte
évolution
webdesign
CMS
Par Artusamak
Julien Dubois

Performances des migrations Drupal avec une indexation des contenus pour Search API

Performances des migrations Drupal avec une indexation des contenus pour Search API
DuaelFr
lun 04/04/2022 - 09:00

Les migrations de grandes quantités de contenus dans Drupal et l'indexation dans un moteur de recherche Search API interne ne font pas bon ménage. Individuellement ce sont des opérations efficaces mais conjointement c'est une catastrophe. Que faire ?

Corps

Lors de la réalisation de nos projets nous sommes souvent amenés à réaliser la migration de grandes quantités de contenus afin d'éviter aux personnes en charge de l'administration du site un travail long et fastidieux de copie. De plus, la plupart des projets de cet ordre font le choix de donner accès à ces contenus par l'entremise d'un ou plusieurs moteurs de recherche aux fonctionnalités plus ou moins avancées. Nous sommes donc régulièrement confrontés à la cohabitation entre le module Migrate qui nous permet de gérer l'import massif de contenus depuis des sources variées et le module Search API qui sert de socle à l'indexation de ces contenus dans les moteurs de recherche.

Migrate comme Search API sont deux outils performants dans l'absolu. Cependant, lorsqu'ils sont utilisés ensemble, le temps nécessaire à l'import et l'indexation des contenus monte en flèche et devient rapidement improductif.

Mais qu'est-ce qui se passe ?


Extrait du sketch "Biouman" des Inconnus

Lorsque Migrate enregistre une entité, cela déclenche automatiquement un processus côté Search API qui peut s'avérer assez coûteux en ressources. En effet, ce dernier va charger tous ses index actifs un par un et vérifier s'il a quelque chose à faire puis procéder à l'indexation en elle-même.

La principale piste qui est généralement identifiée pour résorber ce problème est de désactiver l'option "Indexer les éléments immédiatement". Malheureusement, même si cela réduit effectivement le temps nécessaire aux migrations, ce n'est pas suffisant car Search API a tout de même besoin de consigner l'entité qui devra être indexée plus tard. Il charge donc tous les processeurs de tous ses index actifs pour déterminer si cette entité spécifique sera indexée immédiatement, ultérieurement ou pas du tout. Cette option ne permet donc d'économiser que l'étape d'indexation en elle-même ce qui est insuffisant dans le cas de grandes migrations.

Comment se sortir de cette galère ?


Bob l'éponge a l'air vraiment perdu. Il s'emmêle les bras en
montrant dans toutes les directions

Comme dit précédemment, Search API se préoccupe de tous ses index actifs pour déterminer quoi faire avec le contenu migré. La première solution que vous pouvez donc mettre en place est de désactiver les index avant d'exécuter vos migrations. Cela peut être réalisé avec Drush assez facilement via la commande search-api:disable-all (et sa petite sœur search-api:enable-all lorsque les migrations sont terminées) ou encore carrément en désactivant le serveur via la commande search-api:server-disable (et search-api:server-enable). Si vous ne lancez pas vos migrations via Drush, c'est également réalisable par le code mais nous ne couvrirons pas cela dans cet article.

L'avantage de cette méthode est qu'elle remplit l'objectif de performance en désactivant tout le processus de Search API et qu'elle est relativement simple à mettre en œuvre (une commande avant les migrations, une autre après). Elle présente cependant deux inconvénients importants :

  1. si le serveur ou les index sont désactivés, Search API ne sait pas qu'une entité a été créée ou modifiée et ne l'indexera donc jamais (il ne faisait pas tout ça pour rien quand il était activé avec l'option d'indexation immédiate désactivée) ;
  2. durant toute la durée des migrations, les pages du site s'appuyant sur l'un des index de recherche désactivés ne seront plus accessibles (erreur 500).

Forcer la reconstruction des trackers de Search API

Le premier inconvénient est majeur car cela n'a aucun intérêt d'essayer de résoudre les problèmes de performance de nos migrations si le contenu n'est plus jamais présenté dans les moteurs de recherche. Comme évoqué, cet inconvénient est dû au fait que Search API maintient une liste des contenus qu'il a indexé ou qu'il doit indexer dans la table search_api_item de la base de données. On appelle cette liste son tracker. Lorsque les index sont désactivés, le tracker n'est pas mis à jour et Search API ne sait donc pas qu'il a quelque chose à faire avec ces entités.

Une fois encore, Drush nous facilite la vie en exposant la commande search-api:rebuild-tracker qui, comme son nom l'indique, va imposer à Search API de reconstruire le tracker de ses index et donc de découvrir toutes les entités dont il n'avait pas connaissance auparavant.

Éviter l'indisponibilité des index Search API durant la migration

La seconde problématique n'en est une que si vous avez des migrations qui s'exécutent alors que le site est accessible. Si vos migrations ne font partie que d'un lot joué une seule fois avant la mise en production, cette section ne vous intéresse pas forcément… Cela dit, la solution est tellement simple que cela pourrait vous convaincre davantage que de désactiver les index.

En effet, pour que les index ne soient pas inaccessibles pendant la migration, il suffit de ne pas les désactiver !


Wait… What ?!

Si vous avez suivi depuis le début, vous vous rappelez que l'on a désactivé les index pour que Search API ne perde pas de temps à déterminer s'il faut oui ou non indexer chaque entité que vous importez. Donc si nous les réactivons nous retombons sur le problème de performances que l'on essaie de résoudre ! C'est sans compter une fonctionnalité non documentée de Search API : le paramètre search_api_skip_tracking !

Pour comprendre ce qu'il se passe dans le moteur de Search API, cherchons à comprendre à quel endroit il intervient dans le code. Connaissant un peu la façon dont Drupal est conçu nous pouvons imaginer deux méthodes : un hook ou un événement. Les événements liés à la modification d'une entité n'étant pas courants dans la version actuelle de Drupal, nous allons commencer par nous pencher sur les hooks. Étant donné que c'est une fonctionnalité de bas niveau de Search API, s'il y a un hook il sera situé dans le module search_api et pas l'un de ses sous-modules. De plus, Search API peut indexer tout type d'entité et il est donc peu probable qu'il s'agisse d'une implémentation d'un hook spécifique à un type d'entité donné. Nous allons donc pouvoir chercher dans la base de code une fonction dont le nom commence par search_api_entity_ ce qui nous laisse peu de choix : search_api_entity_delete, search_api_entity_insert, search_api_entity_update, search_api_entity_view et search_api_entity_extra_field_info. Bingo ! Les trois premiers concernent des opérations de création, modification et suppression d'entités génériques.

Lorsque l'on prend une de ces fonctions et que l'on regarde ce qu'il s'y passe en détail, on constate l'appel au service search_api.entity_datasource.tracking_manager et plus spécifiquement à ses méthodes entityInsert, entityUpdate et entityDelete. Chacune d'entre elles teste très rapidement la valeur d'un paramètre search_api_skip_tracking de l'entité et, s'il n'est pas vide, interrompt son exécution.

Sachant donc que cette valeur permet d'arrêter Search API avant qu'il ne consomme des ressources, nous pouvons l'ajouter à notre entité en cours de migration. C'est d'ailleurs très facile car Migrate ne se préoccupe pas vraiment de savoir si une donnée que l'on passe dans son mapping existe ou pas. Il est donc possible d'ajouter une entrée dans les process de nos migrations comme suit :

process:
  # ...
  search_api_skip_tracking:
    plugin: default_value
    default_value: 1
  # ...

Bien évidemment, ceci a pour effet de totalement contourner Search API et il est donc toujours nécessaire de reconstruire ses trackers après la migration comme vu au chapitre précédent.

Le plus simple pour la fin

Maintenant que les contenus ont été importés et que les trackers ont été reconstruits il ne reste plus qu'à indexer tout le contenu pour qu'il devienne disponible sur le site. Une fois encore Drush nous facilite la vie en nous permettant d'accéder à la commande search-api:index mais vous pouvez également passer par l'interface d'admin de Search API si vous préférez.

En résumé

  1. injectez la donnée search_api_skip_tracking dans vos entités via Migrate (ou désactivez vos index mais franchement ça vaut pas le coup) ;
  2. reconstruisez les trackers une fois vos migrations terminées via drush search-api:rebuild-tracker ;
  3. n'oubliez pas d'exécuter l'indexation manuellement une fois les trackers reconstruits via drush search-api:index ;
  4. attendez patiemment le prochain article en vous hydratant bien et en prenant soin de votre santé physique et mentale.

 

Voilà ! Maintenant vous savez comment faire lorsque vous avez à combiner migrations et indexation. Vous vous apercevrez lorsque vous y serez confrontés que l'indexation en elle-même peut prendre un très long temps et même ralentir au fil de son exécution. C'est une problématique a priori liée à la mémoire disponible mais cela fera l'objet d'un prochain article (plus court, c'est promis) !

Catégories
Développement
Drupal
Drupal 8
Drupal 9
Tags
migration
indexation
search_api
optimisation
Par kgaut
Kevin Gautreau

Installer DDEV sur ubuntu

DDEV est une couche d'abstraction à docker et docker-compose permettant de mettre en place une infrastructure pour développer simplement sur un projet drupal sans avoir à installer php, mysql... et autre sur sa machine.

Première étape, installer mkcert qui nous permettra d'avoir des certificats SSL autosignés et donc d'utiliser https sans avertissement :

sudo apt install libnss3-tools -y
wget https://github.com/FiloSottile/mkcert/releases/download/v1.4.3/mkcert-v1.4.3-linux-amd64
sudo cp mkcert-v1.4.3-linux-amd64 /usr/local/bin/mkcert
sudo chmod +x /usr/local/bin/mkcert
mkcert -install

 

Installation de ddev :

curl -LO https://raw.githubusercontent.com/drud/ddev/master/scripts/install_ddev.sh && bash install_ddev.sh

 

Et voila !

Vous pouvez maintenant utiliser ddev sur un projet existant via ddev start ou le configurer sur un nouveau projet via ddev config.

Voici un lien récapitulant les différentes commandes : https://ddev.readthedocs.io/en/stable/users/cli-usage/

Par kgaut
Kevin Gautreau

Drupal 8 & Drupal 9 - importer des fichiers de config dans le code

Voici comment importer via un script où une fonction d'update un ou plusieurs fichiers de config :

# Liste des fichiers de configuration à importer, sans l'extension .yml
$configsToImport = [
  'mon_module.ma_config',
];

# Chemin relative à la racine du drupal
$config_path = '../config/import';
$source = new \Drupal\Core\Config\FileStorage($config_path);

$config_storage = \Drupal::service('config.storage');
foreach ($configsToImport as $configToImport) {
  $config_storage->write($configToImport, $source->read($configToImport));
}

 

Pour rappel il est possible de retrouver automatiquement le dossier d'un module :

# Récupération du chemin du module « mon_module »
$config_path = drupal_get_path('module', 'mon_module') . '/config/install';

 

Par kgaut
Kevin Gautreau

Drupal 8 & Drupal 9 - ajouter une colonne à un champ personnalisé

Si vous avez créé un champ personnalisé dans drupal, associé en tant que champs, ou basefield à un type d'entité et que vous souhaitez le changer (ajouter un attribut par exemple cela peut s'avérer assez compliqué, surtout si votre champs à plusieurs instances dans différents types d'entités.

Je suis tombé sur un helper permettant de finalement réaliser ça simplement : https://gist.github.com/JPustkuchen/ce53d40303a51ca5f17ce7f48c363b9b#fi…

Comment s'y prendre ?

Commencez par modifier votre type de champ et principalement la méthode schema pour ajouter votre attribut

(dans mon cas le fichier est : web/modules/custom/mon_module/src/Plugin/Field/FieldType/ListedItem.php, j'ai ajouté la colonne shortcode.

<?php

namespace Drupal\mon_module\Plugin\Field\FieldType;

use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemBase;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\TypedData\DataDefinition;

/**
* Defines the 'listed' field type.
*
* @FieldType(
*   id = "listed",
*   label = @Translation("Listed"),
*   category = @Translation("General"),
*   default_widget = "listed",
* )
*/
class ListedItem extends FieldItemBase {

  /**
   * {@inheritdoc}
   */
  public function isEmpty() {
    return FALSE;
  }

  /**
   * {@inheritdoc}
   */
  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {

    $properties['menu'] = DataDefinition::create('boolean')
      ->setLabel(t('Menu'));
    $properties['pushs'] = DataDefinition::create('boolean')
      ->setLabel(t('Pushs'));
    $properties['listing'] = DataDefinition::create('boolean')
      ->setLabel(t('Listing'));
    $properties['shortcode'] = DataDefinition::create('boolean')
      ->setLabel(t('Shortcode'));

    return $properties;
  }


  /**
   * {@inheritdoc}
   */
  public static function schema(FieldStorageDefinitionInterface $field_definition) {

    $columns = [
      'menu' => [
        'type' => 'int',
        'size' => 'tiny',
        'default' => 0,
      ],
      'pushs' => [
        'type' => 'int',
        'size' => 'tiny',
        'default' => 0,
      ],
      'listing' => [
        'type' => 'int',
        'size' => 'tiny',
        'default' => 0,
      ],
      'shortcode' => [
        'type' => 'int',
        'size' => 'tiny',
        'default' => 0,
      ],
    ];

    $schema = [
      'columns' => $columns,
    ];

    return $schema;
  }

  /**
   * {@inheritdoc}
   */
  public static function generateSampleValue(FieldDefinitionInterface $field_definition) {

    $values['menu'] = (bool) mt_rand(0, 1);

    $values['pushs'] = (bool) mt_rand(0, 1);

    $values['listing'] = (bool) mt_rand(0, 1);

    $values['shortcode'] = (bool) mt_rand(0, 1);

    return $values;
  }

}

 

Puis copiez l'intégralité du helper dans votre fichier mon_module.install

function _field_type_schema_column_add_helper($field_type, array $columns_to_add = array()) {
  $processed_fields = [];
  $field_type_manager = \Drupal::service('plugin.manager.field.field_type');
  $field_definition = $field_type_manager->getDefinition($field_type);
  $field_item_class = $field_definition['class'];

  $schema = \Drupal::database()->schema();
  $entity_type_manager = \Drupal::entityTypeManager();
  $entity_field_manager = \Drupal::service('entity_field.manager');
  $entity_field_map = $entity_field_manager->getFieldMapByFieldType($field_type);
  // The key-value collection for tracking installed storage schema.
  $entity_storage_schema_sql = \Drupal::keyValue('entity.storage_schema.sql');
  $entity_definitions_installed = \Drupal::keyValue('entity.definitions.installed');

  foreach ($entity_field_map as $entity_type_id => $field_map) {
    $entity_storage = $entity_type_manager->getStorage($entity_type_id);

    // Only SQL storage based entities are supported / throw known exception.
    //    if (!($entity_storage instanceof SqlContentEntityStorage)) {
    //      continue;
    //    }

    $entity_type = $entity_type_manager->getDefinition($entity_type_id);
    $field_storage_definitions = $entity_field_manager->getFieldStorageDefinitions($entity_type_id);
    /** @var Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */
    $table_mapping = $entity_storage->getTableMapping($field_storage_definitions);
    // Only need field storage definitions of address fields.
    /** @var \Drupal\Core\Field\FieldStorageDefinitionInterface $field_storage_definition */
    foreach (array_intersect_key($field_storage_definitions, $field_map) as $field_storage_definition) {
      $field_name = $field_storage_definition->getName();
      try {
        $table = $table_mapping->getFieldTableName($field_name);
      } catch (SqlContentEntityStorageException $e) {
        // Custom storage? Broken site? No matter what, if there is no table
        // or column, there's little we can do.
        continue;
      }
      // See if the field has a revision table.
      $revision_table = NULL;
      if ($entity_type->isRevisionable() && $field_storage_definition->isRevisionable()) {
        if ($table_mapping->requiresDedicatedTableStorage($field_storage_definition)) {
          $revision_table = $table_mapping->getDedicatedRevisionTableName($field_storage_definition);
        }
        elseif ($table_mapping->allowsSharedTableStorage($field_storage_definition)) {
          $revision_table = $entity_type->getRevisionDataTable() ?: $entity_type->getRevisionTable();
        }
      }
      // Load the installed field schema so that it can be updated.
      $schema_key = "$entity_type_id.field_schema_data.$field_name";
      $field_schema_data = $entity_storage_schema_sql->get($schema_key);

      $processed_fields[] = [$entity_type_id, $field_name];
      // Loop over each new column and add it as a schema column change.
      foreach ($columns_to_add as $column_id) {
        $column = $table_mapping->getFieldColumnName($field_storage_definition, $column_id);
        // Add `initial_from_field` to the new spec, as this will copy over
        // the entire data.
        $field_schema = $field_item_class::schema($field_storage_definition);
        $spec = $field_schema['columns'][$column_id];

        // Add the new column.
        $schema->addField($table, $column, $spec);
        if ($revision_table) {
          $schema->addField($revision_table, $column, $spec);
        }

        // Add the new column to the installed field schema.
        if ($field_schema_data) {
          $field_schema_data[$table]['fields'][$column] = $field_schema['columns'][$column_id];
          $field_schema_data[$table]['fields'][$column]['not null'] = FALSE;
          if ($revision_table) {
            $field_schema_data[$revision_table]['fields'][$column] = $field_schema['columns'][$column_id];
            $field_schema_data[$revision_table]['fields'][$column]['not null'] = FALSE;
          }
        }
      }

      // Save changes to the installed field schema.
      if ($field_schema_data) {
        $recipient_column = $table_mapping->getFieldColumnName($field_storage_definition, 'recipient');
        unset($field_schema_data[$table]['fields'][$recipient_column]);
        if ($revision_table) {
          unset($field_schema_data[$revision_table]['fields'][$recipient_column]);
        }
        $entity_storage_schema_sql->set($schema_key, $field_schema_data);
      }
      if ($table_mapping->allowsSharedTableStorage($field_storage_definition)) {
        $key = "$entity_type_id.field_storage_definitions";
        if ($definitions = $entity_definitions_installed->get($key)) {
          $definitions[$field_name] = $field_storage_definition;
          $entity_definitions_installed->set($key, $definitions);
        }
      }
    }
  }
}

Ensuite créez une fonction d'update qui va modifier les schémas de l'ensemble des instance de votre champs en appelant le helper.

Dans mon cas, mon id de champs est listed et je souhaite ajouter la colonne shortcode :

/**
* node.listed add column shortcode
*/
function mon_module_update_8039() {
  _field_type_schema_column_add_helper('listed', ['shortcode']);
}

Et voila !

Sur le lien mentionné il y a d'autres exemples pour d'autres usages, que je n'ai pas tester.

Par admin

Statistiques 2022 de notre espace Slack

Mise à jour des statistiques d'utilisation de notre espace Slack, un an plus tard !

L'an dernier, nous avions listé quelques informations intéressantes sur notre usage de Slack : . Malheureusement la comparaison sera difficile, car les éléments auxquels nous avons accès ont changé depuis. Il n'est plus possible de voir certaines informations "toutes périodes confondues", il faudra donc se contenter des 30 derniers jours.

Membres actifs

Du 16/02/2022 au 18/03/2022

Souscription (par semaine) - du 16/02/2022 au 18/03/2022

Souscription (par jour) - du 16/02/2022 au 18/03/2022

Utilisation des canaux

Depuis leur création

Liste des canaux (1/3)  - Depuis leur création

Liste des canaux (2/3) - Depuis leur création

Liste des canaux (3/3) - Depuis leur création

Répartition des messages

Du 16/02/2022 au 18/03/2022

Répartition des messages (date d'envoi) - du 16/02/2022 au 18/03/2022

Répartition des messages (lecture) - du 16/02/2022 au 18/03/2022

Répartition des messages (écriture) - du 16/02/2022 au 18/03/2022

Je pense continuer à regarder ses statistiques chaque année, pour avoir des points de comparaison. Si vous avez des suggestions, n'oubliez pas que le canal #orga-slack est à votre disposition !

PS
Je n'ai pas eu le temps de récupérer les données autrement que via capture d'écran pour l'instant, j'ai bien conscience que ce n'est pas idéal. Si cela est bloquant, n'hésitez pas à nous demander des détails via bureau@drupal.fr.

Par Artusamak
Julien Dubois

Comprendre les tests automatisés

Comprendre les tests automatisés
DuaelFr
ven 25/02/2022 - 09:19

J'ai récemment eu à accompagner plusieurs équipes sur le sujet des tests automatisés ce qui m'a amené à rechercher des ressources sur Internet pour approfondir les notions que j'avais un peu acquises sur le tas au travers de mes contributions au cœur de Drupal. Le monde des tests est très vaste alors il me semble important d'avoir une bonne culture générale du sujet avant de se lancer étant donné que cela aura un impact sur la conception de votre stratégie de tests.

Vous trouverez donc ci-dessous quelques liens qui vous mèneront vers des articles du plus généraliste au plus spécifique.

Catégories
Par Artusamak
Julien Dubois

Améliorer son référencement pour prendre en charge les types d'entités personnalisés dans Pathauto

Améliorer son référencement pour prendre en charge les types d'entités personnalisés dans Pathauto
Artusamak
lun 21/02/2022 - 08:50

Lorsque vous créez un type d'entité personnalisé, vous voulez bénéficier des fonctionnalités tierces liées aux types de contenu (vues, révisions, traduction...). La génération des alias pour le référencement avec Pathauto est l'un des points incontournables.

Corps

Vous venez de créer un nouveau type d'entité. Vous contemplez votre œuvre, réfléchissant à la prochaine touche à ajouter pour la parfaire. Tout à coup, un éclair vous frappe : "Il nous faut prendre en charge les alias Pathauto". Évidemment ! Pourquoi se priver de la puissance de cet outil ? C'est l'un des modules indispensables de Drupal 9 qui vous permet d'améliorer la qualité de votre référencement (du SEO éthique et responsable bien sûr !). Comme il est 16h et que la fin de journée approche, vous espérez pouvoir boucler ça rapidement pour reprendre votre marathon visionnage de l'intégrale de Columbo au plus vite.

Scénario 1 : Je suis une personne chanceuse

L'accident heureux consiste à vous rendre dans l'interface de Pathauto et de voir si votre type d'entité n'est pas déjà visible. Si tel est le cas, vous aurez le temps de vous faire un épisode de plus car la journée est terminée, cela fonctionne. Pour les gens moins chanceux, voici ce qu'il faut faire pour que cela fonctionne.

Scénario 2 : J'ai besoin de débrider le chemin de chaque entité

L'intérêt d'un système de gestion de contenu est de maîtriser les URLs de ses contenus. Vous pouvez opter pour de la génération automatique mais vouloir débrider cette génération entité par entité (comme pour les nœuds).

Pathauto est pré-configuré pour prendre en charge n'importe quel type d'entité. La magie se passe dans \Drupal\pathauto\Plugin\Deriver\EntityAliasTypeDeriver::getDerivativeDefinitions(). Trois critères sont à respecter pour que cela fonctionne clé en main.

1. Votre type d'entité doit déclarer un template de lien "canonical".

# inspectors/src/Entity/Inspector.php

/**
* Defines the Inspector entity class.
*
* @ContentEntityType(
*   ...
*   links = {
*     "add-form" = "/admin/content/inspector/add/{inspector}",
*     "add-page" = "/admin/content/inspector/add",
*     "canonical" = "/inspector/{inspector}",
*     "edit-form" = "/admin/content/inspector/{inspector}/edit",
*     "delete-form" = "/admin/content/inspector/{inspector}/delete",
*     "collection" = "/admin/content/inspector"
*   },
*   ...
* )
*/
class Inspector extends RevisionableContentEntityBase {}

2. Votre type d'entité doit être fieldable.

3. Votre bundle doit avoir un champ "path" qui stockera le chemin vers l'entité pour les cas où vous voulez débrider.

Si vous remplissez ces trois critères, votre type d'entité est maintenant pleinement utilisable dans Pathauto. Vous pouvez fermer votre CMS préféré et retourner à votre visionnage, vous n'avez raté que la première moitié de l'épisode.

Scénario 3 : Je n'ai pas de champ "path" ou n'en ai pas besoin

Si le champ "path" peut être intéressant dans certains cas, il arrivera que vos types d'entités soient plus basiques. Dans ce cas, comment l'exposer à Pathauto ? Il y a un petit peu plus de travail mais rien d'insurmontable. La solution consiste à implémenter un plugin AliasType. (Si vous ne savez pas comment fonctionnent les plugins, je vous invite à relire notre article). N'oubliez pas de déclarer son annotation @AliasType.

# inspectors/src/Plugin/pathauto/AliasType/InspectorsAliasType.php

/**
* Defines the Inspector entity class.
*
* @AliasType(
*   id = "inspector_aliases",
*   label = @Translation("Inspectors"),
*   types = {"inspector"},
*   context_definitions = {
*     "inspector" = @ContextDefinition("entity:inspector")
*   }
* )
*/
class InspectorsAliasType extends EntityAliasTypeBase {}

Les deux attributs de l'annotation à regarder de près sont types qui liste des types d'entités pour lesquels votre plugin va s'appliquer et context_definitions qui permet d'accéder à la liste des tokens de votre type d'entité (et donc ses champs, ses métadonnées et toutes les fonctionnalités avancées de Pathauto).

Ne vous précipitez pas tout de suite sur la génération de vos alias car vous risquez d'être déçu(e). La configuration est possible mais il reste une étape importante pour pouvoir profiter de tout cela, déclencher la génération. Si l'on ne donne pas un coup de pouce au système, la génération de vos alias ne se fera jamais. Pathauto implémente les hook_entity_OP() pour déclencher la génération mais si vous n'avez pas de canonical ou de champ path comme évoqué précédemment, vous devrez déclencher vous même le générateur.

Les alias doivent se créer, se mettre à jour et se supprimer en fonction de l'opération effectuée sur votre entité, vous allez donc devoir implémenter vous aussi les hook_entity_OP(). Comme on cible un type d'entité précis, les hooks à implémenter sont hook_ENTITY_TYPE_OP(). Cela donne ce code :

# inspectors.module

/**
* Implements hook_ENTITY_TYPE_update().
*/
function inspectors_inspector_update(Drupal\Core\Entity\EntityInterface $entity) {
  $generator = \Drupal::service('pathauto.generator');
  try {
    $generator->createEntityAlias($entity, 'update');
  }
  catch (\InvalidArgumentException $e) {
    $generator->messenger()->addError($e->getMessage());
  }
}

/**
* Implements hook_ENTITY_TYPE_insert().
*/
function inspectors_inspector_insert(Drupal\Core\Entity\EntityInterface $entity) {
  $generator = \Drupal::service('pathauto.generator');
  try {
    $generator->createEntityAlias($entity, 'insert');
  }
  catch (\InvalidArgumentException $e) {
    $generator->messenger()->addError($e->getMessage());
  }
}

/**
* Implements hook_ENTITY_TYPE_delete().
*/
function inspectors_inspector_delete(EntityInterface $entity) {
  \Drupal::service('pathauto.alias_storage_helper')->deleteEntityPathAll($entity);
}

Une fois vos hooks implémentés, vous devriez pouvoir tester la génération des alias et si tout s'est bien passé, cela devrait fonctionner.

Bonus : générer en masse les alias

Il vous reste une dernière action à faire si voulez bénéficier de la génération en masse des alias. Il faut implémenter la méthode \Drupal\mobility_plans\Plugin\pathauto\AliasType\MobilityPlanAliasType::bulkUpdate() dans votre plugin d'alias.

# inspectors/src/Plugin/pathauto/AliasType/InspectorsAliasType.php

class InspectorsAliasType extends EntityAliasTypeBase {

  /**
   * Update the URL aliases for multiple entities.
   *
   * @param array $ids
   *   An array of entity IDs.
   * @param array $options
   *   An optional array of additional options.
   *
   * @return int
   *   The number of updated URL aliases.
   */
  protected function bulkUpdate(array $ids, array $options = []) {
    $options += ['message' => FALSE];
    $updates = 0;
    $generator = \Drupal::service('pathauto.generator');

    $entities = $this->entityTypeManager->getStorage($this->getEntityTypeId())->loadMultiple($ids);
    foreach ($entities as $entity) {
      // Update aliases for the entity's default language and its translations.
      foreach ($entity->getTranslationLanguages() as $langcode => $language) {
        $translated_entity = $entity->getTranslation($langcode);

        try {
          $result = $generator->createEntityAlias($translated_entity, 'update');
        }
        catch (\InvalidArgumentException $e) {
          $generator->messenger()->addError($e->getMessage());
        }

        if ($result) {
          $updates++;
        }
      }
    }

    if (!empty($options['message'])) {
      $this->messenger->addMessage($this->translationManager
        ->formatPlural(count($ids), 'Updated 1 %label URL alias.', 'Updated @count %label URL aliases.'), [
        '%label' => $this->getLabel(),
      ]);
    }

    return $updates;
  }

}

Et nous y voilà ! À vous les alias finement ciselés pour parfaire votre chef d'œuvre ! Vous pouvez commiter tout cela et retourner prendre des nouvelles de Peter Falk, il est sur le point d'attraper le meurtrier et résoudre l'enquête.

Catégories
Développement
Drupal
Drupal 8
Drupal 9
Tags
pathauto
type d'entité
seo
alias
Par Simon Georges
Simon Georges
Drupal depuis plus de 10 ans, SEO depuis 3 ans

Migration Drupal 7 à 9 et évolutions du site Tramil

Créé en 1982, Tramil est un programme de recherche appliquée à l'usage populaire des plantes médicinales dans la Caraïbe. L'objectif de ce programme est de valider scientifiquement les usages traditionnels des plantes médicinales pour les soins primaires.

Par Artusamak
Julien Dubois

11 raisons de choisir Drupal pour votre site web

11 raisons de choisir Drupal pour votre site web
stephanie@happyculture.coop
lun 06/12/2021 - 10:25

Drupal s’est imposé comme une référence parmi les meilleures solutions pour la réalisation de sites web. Il fait partie du top 6 des systèmes de gestion de contenu. C’est une solution robuste, flexible et fiable, qui sait s’adapter aux évolutions et aux attentes des utilisateurs.







Corps

Drupal est un CMS, ou SGC en français, libre et ouvert, écrit en PHP en 2001.
Conçu pour couvrir un large éventail de types de sites, il s’est imposé comme l’un des acteurs majeurs de la sphère web.

Il existe plusieurs options pour créer des sites web, mais chez Happyculture, nous les concevons avec Drupal depuis presque 15 ans. C’est pour nous l’outil idéal pour réaliser votre site internet de contenu et pour vous convaincre, nous vous avons listé les 11 principales raisons. 

1/ Compatibilité

Site internet, intranet ou encore extranet, site vitrine ou e-commerce, de quelques pages à des millions de contenus, multilingue… Drupal est conçu pour couvrir un large éventail de types de sites, du plus simple au plus complexe grâce à son évolutivité. Il saura s’adapter aux besoins de votre infrastructure pour encaisser des pics de trafic réguliers ou un grand volume de visiteurs.

2/ Simplicité d’utilisation

D’une manière générale, la gestion de contenu est un point fort de Drupal. Ainsi, Drupal permet de créer facilement des contenus et de les afficher sous forme de listes, de messages, de galeries, de tableaux, de cartes ou de blocs : il suffit simplement de remplir des champs qui constituent des types de contenu. Et pour vos textes riches, il vous facilite la saisie via l’éditeur WYSIWYG CKEditor 4 (et bientôt 5 !). 

3/ Modularité

Drupal est riche d'un écosystème bien vivant depuis 2001 qui lui permet de compléter les fonctionnalités variées et proposées par le cœur de Drupal. De cette force est né l'adage "il y a un module pour ça", décrivant la profondeur du catalogue de modules gratuits à disposition.
Tous les 6 mois, Drupal publie également une mise à jour avec de nouvelles fonctionnalités afin de rester en phase avec son marché et la demande des utilisateurs.

4/ Des technologies dans l’air du temps

Thèmes compatibles avec le “responsive design” et le “mobile friendly”, utilisation du HTML5, intégration avec des webservices, meilleur respect des standards : Drupal s’appuie sur les pratiques du web moderne, favorisant le référencement naturel et l’accessibilité.

5/ Pérennité

Choisir Drupal, c’est faire le choix de l’open source pour ne pas être lié à une solution CMS propriétaire empêchant les évolutions de prestataire et le contrôle des coûts. C’est un outil gratuit et ouvert.
Dès sa création, la communauté mondiale de Drupal n'a eu de cesse de trouver des solutions pour s'assurer que Drupal soit un outil pérenne et ne se laisse pas dépasser par le dynamisme du marché. Publication de correctifs de sécurité réguliers, maintenance mensuelle, conférences pluriannuelles internationales et nationales permettent à la communauté de faire vivre la solution.

6/ Communautaire

Drupal s’appuie sur un réseau mondial de plus d’1 million d’utilisateurs dont 31 000 développeurs dans plus de 230 pays et plus de 3 000 contributeurs à son cœur. C’est l'un des plus gros projets open source au monde.
Happyculture fait d’ailleurs partie de ces contributeurs et reverse régulièrement du code depuis plusieurs années. Happyculture contribue à l’organisation de la communauté en étant impliquée dans les événements nationaux, en proposant des conférences ou en animant des ateliers. Ce qui fait  de nous l’une des 70 sociétés les plus prolifiques au monde par leur contribution au cœur de Drupal.

7/ SEO optimisé

On ne peut pas parler site web sans aborder la question du SEO. Votre site a besoin d’un minimum de visibilité. Drupal propose alors une suite d’outils SEO pour optimiser le référencement naturel de votre site et améliorer son positionnement dans les résultats des moteurs de recherche.

8/ Accessibilité

Drupal propose clé en main une solution compatible avec les exigences WCAG 2.0 équivalentes au niveau bronze/A du RGAA 3.0 et ambitionne d’atteindre le niveau argent/AA.
C’est un des seuls outils à proposer un tel niveau d’exigence clé en main. Il reste de votre responsabilité de maintenir ce niveau d’accessibilité lors de la rédaction de vos contenus ou la création de votre identité graphique pour ne pas perdre en qualité.
Nous vous renvoyons vers notre article dédié à l’accessibilité pour (re)découvrir quelques points de vigilance et conseils de mise en œuvre.

9/ Sécurité

La communauté Drupal assure le suivi des failles de sécurité, la publication de correctifs et la mise à disposition des utilisateurs d’informations pour assurer la sécurité de leurs sites web contre les attaques. 
Drupal dispose de milliers de modules complémentaires centralisés sur le site officiel drupal.org. Cela permet de garantir la couverture par son équipe de sécurité et vous protéger d’éventuelles attaques ou fuites de données (si votre site applique les mises à jour !). Les modules sont développés par la communauté, 85% par des personnes payées pour le faire, 15% par des bénévoles.
Autant dire que Drupal est bien sécurisé !

10/ Réversibilité 

L’une des raisons intéressantes qui jouent en faveur de Drupal est la facilité à trouver un autre prestataire pour reprendre un projet en cours, c’est le principe de réversibilité. Vous pouvez récupérer l’intégralité de la base de code et de la base de données, les installer très simplement chez un autre prestataire et continuer à faire vivre votre site. Mais cela peut dépendre de votre contrat avec votre prestataire, pensez à vérifier !

11/ Une référence dans le monde

Drupal est une solution qui dispose notamment d’une belle notoriété dans les secteurs de l’éducation et de la recherche, mais également dans la santé, auprès de gouvernements ou encore de structures de l’ESS. 

En France :

Dans le monde :

Et bien d’autres encore :

Drupal est aujourd’hui l’un des meilleurs systèmes de gestion de contenu et nous espérons que les raisons citées vous ont convaincu ou donné envie d’en savoir plus. 
Alors, si vous souhaitez lancer un projet ou avez des questions sur l’utilisation de Drupal, n'hésitez pas à nous contacter.
 

Catégories
Développement
Drupal
Drupal 10
Drupal 9
Tags
Drupal
CMS
accessibilité
seo
Par Iloofo
Iloofo

Vulgarisation: Fonctionnement des Cache tags sous Drupal

Fonctionnement historique des caches

Comme beaucoup de sites web et de systèmes de gestion de contenu, avant sa version 8, Drupal gérait les caches en fonction d’une temporalité. Celle-ci devait donc être suffisamment longue pour permettre de soulager le serveur, mais suffisamment courte pour permettre d’avoir un contenu à jour.

La mise à jour des pages en cache était aisée pour une page de contenu lorsque le contenu de celle-ci était mis à jour (possibilité de demander la suppression du cache de la page en question), mais plus compliquée lorsqu’il s’agissait de pages de listing où ce contenu était censé apparaître : difficile de savoir sur quelles pages de listing le contenu est ou devrait être remonté.

Ainsi par exemple, un cache était généré pour une durée de 5 minutes, et donc distribué et stocké par les couches intermédiaires tels qu’un reverse proxy Varnish pendant 5 minutes sans nécessairement avoir la possibilité d’invalider ces caches.

Fonctionnement actuel via Tags

Depuis Drupal 8, les caches de Drupal fonctionnent via le principe d’étiquettes de cache (ou Cache tags), et non plus uniquement de temporalité.

Les caches doivent par défaut avoir une durée de vie importante (recommandé à 1 an) pour permettre une mise en cache par défaut longue, puis gérer la mise en cache et la re-génération des caches à la demande en fonction de la création/mise à jour du contenu.

Une page est générée à partir de plusieurs éléments imbriqués que l’on nommera composants. Exemple : le rendu d’un contenu, un bloc de listing de contenu, un template de rendu d’un élément etc.

On attribue un ou plusieurs tags à chaque composant qui reflètent le contenu de celui-ci.

Exemple : node:1 pour le rendu du contenu node:1, ou node:10 node:11 node:12 liste_actualites pour un bloc de listing des actualités qui affiche les nodes 10, 11 et 12.

Par Artusamak
Julien Dubois

Pourquoi encore choisir un CMS pour son site web en 2022 ?

Pourquoi encore choisir un CMS pour son site web en 2022 ?
stephanie@happyculture.coop
mar 02/11/2021 - 09:44

Au fil du temps, la production de sites internet s’industrialise. Le coût d’entrée d’un site s’est considérablement abaissé et plusieurs options s’offrent à vous lorsque vous devez lancer un nouveau site. Explorons-les ensemble.







illustration des différentes fonctionnalités d'un CMS
Corps

Mais c’est quoi un CMS ?

Un CMS, ou SGC en français, est un logiciel ou une plateforme permettant de créer et modifier facilement le contenu qui alimente un site internet. Le contenu peut être généré par une personne seule ou une équipe de webmasters mais il est également possible de laisser les visiteurs publier leur propre contenu. On parle dans ce cas de contenu généré par les utilisateurs (UGC).

Le CMS est protéiforme, il peut gérer votre site institutionnel, votre boutique en ligne, votre blog, votre médiathèque, votre site d’offres d’emploi.... Bien configuré, il peut propulser des sites allant d’une dizaine de visiteurs jusqu’à plusieurs dizaines de milliers par jour.
Un système de gestion de contenu est dans sa zone de confort pour la saisie, la validation, la classification, la gestion de médias, la configuration du référencement (SEO), l’attribution de rôles/droits à des utilisateurs(rices), l’agrégation, la navigation au sein de ces contenus...

Les CMS ne sont bien sûr pas la seule solution pour créer un site, mais ils sont accessibles et possèdent une base de fonctionnalités déjà existantes et suffisamment complètes. En optant pour un CMS, vous avez déjà un panel de fonctionnalités à votre disposition.

Le CMS peut être open source (Drupal, Wordpress, Prestashop…) ou propriétaire (Sitecore, Kentico, Adobe site manager...). Selon votre choix, des coûts de licence peuvent s’appliquer et votre niveau d’autonomie pour modifier / voir sous le capot varie très fortement.
À l’heure où les supports et canaux se multiplient pour se spécialiser (applications mobiles, réseaux sociaux, site institutionnel, site RH, site du support utilisateurs…), une constante est toujours présente : le besoin de rédiger votre contenu ! Vous avez donc toujours un intérêt à avoir un système de gestion de contenu au sein de votre structure.

Le marché tend à se rapprocher du modèle suivant : vous créez un site dédié à l’administration de votre contenu pour centraliser votre contenu et vos sites / applications se connectent à ce système de gestion de contenu pour présenter les bons contenus au(x) bon(s) endroit(s). Grâce à cette mutualisation vous simplifiez la mise à jour de l’information en évitant la répétition.

 

Faites votre choix

Chaque structure a ses propres besoins et le modèle décrit ci-dessus ne s’applique pas forcément à votre organisation. Rassurez-vous, il existe des solutions pour chaque taille de structure / projet. Passons en revue vos options de la moins onéreuse à la plus onéreuse.

Nous ne vous détaillerons pas ici, ni ailleurs, les avantages et inconvénients de chacun des logiciels car il en existe plusieurs dizaines dans chaque langage (PHP, Python, Ruby…). De plus, nous estimons que seule l’expérience d’utilisation et la mise en œuvre de ces outils permettrait de donner un avis objectif et légitime. Ce n’est pas notre cas, nous sommes experts Drupal.

À noter que nous mentionnons le terme de réversibilité dans les 3 options, ce terme désigne la capacité à repartir avec le code de votre site et vos contenus pour pouvoir les mettre chez un autre prestataire / hébergeur et les modifier.
 

Option 1 : Un site générique, hébergé sur une plateforme SaaS

Ce peut être l’offre de votre hébergeur type Ionos (1&1) ou un service dédié type Wix, Hubside. Il existe aussi des services spécialisés si vous voulez monter une boutique par exemple : Squarespace ou Shopify sont les services les plus connus.

Pour quelques euros par mois vous pouvez choisir parmi une collection de gabarits et ambiances visuelles celui qui vous plaît pour ensuite modifier le contenu des pages.
Les possibilités de personnalisation sont très limitées mais pour un site simple (type plaquette), cette option fait le travail. Vous n’avez pas à vous préoccuper de la maintenance, de l’hébergement, des sauvegardes. Tout est compris dans l’offre.

La contrepartie est que vous ne pourrez pas transformer le site pour en faire ce que vous voulez si le site doit évoluer au bout de quelques mois ou années. Vous ne pourrez pas non plus repartir avec le code source du site (réversibilité) pour l’héberger ailleurs ou le faire modifier par un(e) développeur(se). C’est la plateforme sur laquelle vous créez votre site qui est propriétaire de vos données.

Le coût de ces services est très accessible :

  • Coût de la conception et du développement : Gratuit si vous le faites vous même. Quelques centaines d’euros si vous passez par un prestataire.
  • Adaptabilité aux besoins métiers : Inexistante
  • Coût récurrent tout au long de la vie du site : 
    • Licence : Entre 1 et 50 € par mois pour le service
    • Hébergement : Compris
    • Maintenance : Compris
  • Personnalisation à votre image de marque : Inexistante à Faible
  • Connaissances techniques requises : Aucune
  • Réversibilité : Impossible

 

Option 2 : Un site sur mesure à partir d’un CMS

Si vous souhaitez un site qui reflète fidèlement votre identité visuelle et pour lequel l’expérience de navigation est taillée sur mesure pour vos contenus, alors le site hébergé sur une plateforme tierce ne conviendra pas. Vous aurez besoin de gérer votre site en autonomie.

Selon que vous possédiez les compétences au sein de votre structure ou via un prestataire type agence web (tel qu’Happyculture ;-)), les étapes de conception de l’interface (Design / Responsive), l’organisation de la circulation au sein des pages (ergonomie et organisation de l’information) et le développement seront des passages obligés pour rendre du mieux possible un service à vos visiteurs.

Pour construire ce site sur mesure, plutôt que de partir d’une feuille blanche, le CMS est l’outil nécessaire à votre projet pour les raisons mentionnées précédemment.
Avec un CMS vous partez d’un socle de fonctionnalités extensible. L’équipe technique se charge de configurer et enrichir ce socle en piochant dans la bibliothèque de modules complémentaires gratuits ou payants. Si vos besoins sont pointus et non couverts par un module complémentaire, les développeurs peuvent créer des fonctionnalités sur mesure. Dans certains cas, il pourra être nécessaire de déconstruire certaines fonctionnalités pour les redévelopper si le comportement par défaut ne vous convenait pas (ex : recherche de contenu sur mesure).

Drupal dispose de milliers de modules complémentaires centralisés sur le site officiel drupal.org. Cela permet de garantir la couverture par son équipe de sécurité et vous protéger d’éventuelles attaques ou fuites de données (si votre site applique les mises à jour (!)). Les modules sont développés par la communauté, 85% par des personnes payées pour le faire, 15% par des bénévoles.

Pour maîtriser votre image de marque et l’organisation de votre contenu votre site devra donc être hébergé sur vos serveurs ou chez un hébergeur. Selon la taille du site, le coût varie de quelques dizaines à quelques centaines d’euros par mois.

Il faudra ajouter à cela une ligne budgétaire dédiée à la maintenance du site. Qu’elle soit corrective ou évolutive, votre site vit au-delà de sa mise en ligne initiale. Des failles de sécurité peuvent être découvertes et votre site doit être mis à jour pour que vous restiez protégés. Des bugs peuvent également être corrigés par la communauté qui développe ces modules et vous en faire bénéficier gratuitement en appliquant ces mises à jour.

Pour résumer, vous êtes pleinement propriétaires de votre site, vous maîtrisez la mise en forme, l’organisation du contenu. 

Le coût de la conception et du développement représentent l’essentiel de la création du site mais permettent de se distinguer de ses concurrents et de garantir une réponse aux besoins de vos visiteurs.

  • Coût de la conception et du développement : Plusieurs milliers à dizaines de milliers d’euros selon la taille du site
  • Adaptabilité aux besoins métiers : Moyenne
  • Coût récurrent tout au long de la vie du site : 
    • Licence : 0 € pour les CMS open source
    • Hébergement : À partir de 50 € par mois
    • Maintenance : À partir de 100 € par mois pour une version minimale (correctifs de sécurité), plus si on ajoute des correctifs autres + des évolutions
  • Personnalisation à votre image de marque : Totale
  • Connaissances techniques requises : Une équipe technique interne ou un prestataire est indispensable
  • Réversibilité : Possible (peut dépendre du contrat, pensez à vérifier !)

 

Option 3 : Un site sur mesure à partir d’une page blanche

La troisième et dernière option qui s’offre à vous et votre équipe technique est l’utilisation d’un Framework (Symfony, Express, Django, Ruby on Rails…). Un framework est une boîte à outils qui permet à l’équipe technique de construire un outil personnalisé de A à Z. Vous tirerez les mêmes bénéfices que l’option 2 et irez plus loin dans la personnalisation en imaginant également la partie administration du site sur mesure.

Ce cas peut être intéressant pour des sites qui comportent une partie “métier” forte qui ne peut pas être réalisée via des modules complémentaires et le cœur d’un CMS ou qui nécessiteraient beaucoup de développements sur mesure.

Cette solution d’une certaine façon implique de réinventer la roue pour la saisie et l’administration des contenus car toutes les fonctionnalités de saisie du contenu et d’administration doivent être développées, là où le CMS propose une solution clé en main. C’est autant de budget en plus à y dédier.

Les avantages du Framework comparés au CMS sont faibles, le seul cas qui justifiera le surcoût sera l’intégration de nombreuses fonctionnalités métier.

  • Coût de la conception et du développement : Plusieurs milliers à dizaines de milliers d’euros selon la taille du site
  • Adaptabilité aux besoins métiers : Totale
  • Coût récurrent tout au long de la vie du site :
    • Licence : 0 €
    • Hébergement : À partir de 50 € par mois
    • Maintenance : À partir de 100 € par mois pour une version minimale (correctifs de sécurité), plus si on ajoute des correctifs autres + des évolutions
  • Personnalisation à votre image de marque : Totale
  • Connaissances techniques requises : Une équipe technique interne ou un prestataire est indispensable
  • Réversibilité : Possible (peut dépendre du contrat, pensez à vérifier !)

 

Conclusion

Voici un tableau récapitulatif des différents critères que nous vous avons présentés ci-dessus.

  Option 1 :
Site SaaS

Option 2 :
Site CMS

Option 3 :
Site Framework
Coût de la conception et du développement + +++ ++++
Adaptabilité aux besoins métiers Impossible ++ +++
Personnalisation à votre image de marque + +++ +++
Connaissances techniques requises + +++ +++
Réversibilité Impossible Possible Possible
Coût récurrent tout au long de la vie du site :
Licence / Abonnement ++ Gratuit (open source)
 / 
+ (propriétaire)
Gratuit
Hébergement Compris ++ ++
Maintenance Compris ++ ++

 

Avec toutes ces informations, nous espérons que vous y voyez plus clair sur l’intérêt d’un CMS et les situations où il est adapté.

Si vous comptez lancer un projet ou souhaitez des conseils sur l’organisation de votre contenu, n’hésitez pas à nous transmettre vos questions.

Catégories
Développement
Drupal
Drupal 9
Par Artusamak
Julien Dubois

Mettre à jour vers Drupal 9 à l'aide de Lenient

Mettre à jour vers Drupal 9 à l'aide de Lenient
DuaelFr
lun 11/10/2021 - 09:00

À ce jour il reste un peu plus de 3000 modules qui n'ont pas encore été mis à jour de Drupal 8 vers Drupal 9. Découvrez dans cet article comment contourner ce problème pour monter la version de votre site.







Corps

Comme nous l'indiquions dans un précédent article, Drupal 8 cessera d'être supporté le 2 novembre 2021 soit, à l'heure où cet article est écrit, dans moins d'un mois. Or, même si les mises à jour majeures ont été largement simplifiées depuis la sortie de Drupal 8, le fait d'avoir plusieurs modules en retard peut être complexe à gérer pour passer à cette nouvelle version majeure. En effet, chaque module (ou thème) déclare la ou les versions avec lesquelles il est compatible et si la personne qui le maintient n'est plus très réactive cela peut retarder votre propre montée de version.

Fonctionnement concret du système de gestion des dépendances

Concrètement, à partir du fichier info.yml des modules, le serveur packagist de Drupal va générer un arbre de dépendances. Lorsque votre composer va réclamer une mise à jour, cet arbre de dépendances sera analysé pour vérifier que tous vos paquets (core, modules, thèmes, etc.) sont compatibles entre eux. Un module qui ne déclarera donc pas officiellement supporter Drupal 9 ne sera pas reconnu comme compatible avec une montée de version du cœur et bloquera donc la procédure.

La mise à jour de Drupal 8 vers Drupal 9 étant principalement liée au remplacement de code déprécié et à la déclaration effective du support de la nouvelle version, la communauté a mis en place il y a plusieurs mois un robot qui est passé sur tous les modules ayant une version compatible avec Drupal 8 pour y indiquer les problématiques à traiter et proposer un patch lorsque c'était possible. Cependant, tant que ce patch n'est pas intégré par les personnes en charge de la maintenance des modules, le système de gestion des dépendances ne peut pas mettre à jour son arbre. En effet, même si vous appliquez le patch localement, cela intervient après le calcul des dépendances et ne permet donc pas de contourner le problème.

Initiative d'accélération des mises à jour

Face à l'approche de la fin de vie de Drupal 8, la communauté propose deux pistes pour aider la transition à se faire.

Ouverture à l'adoption des modules

Tous les modules et thèmes ayant une version de Drupal 8 mais pas de Drupal 9 ont été ouverts à l'adoption. Au terme d'une période de deux semaines durant laquelle les personnes en charge de la maintenance peuvent choisir de refuser de céder leur place (et potentiellement faire le nécessaire pour corriger le problème de compatibilité), il est possible pour quiconque dans la communauté de demander à se faire transférer la charge pour prendre la suite et rendre le module ou le thème compatible.

Création du point d'entrée composer Lenient

Auparavant, la méthode recommandée pour contourner le problème de gestion des dépendances de composer était de déclarer manuellement, pour chaque module ou thème impliqué, un repository personnalisé pour aller récupérer le code directement via git au lieu de passer par le packagist de Drupal. C'était un processus fonctionnel mais très fastidieux. La communauté, à l'écoute de tous les gestionnaires de sites en détresse, a donc mis en place un nouveau service appelé Lenient. C'est un nouveau dépôt packagist qui ne contient que les modules n'ayant pas encore de compatibilité Drupal 9 et qui ne déclare pas de dépendance sur le cœur de Drupal. Il vous permet ainsi de monter votre version du cœur sans blocage et d'appliquer ensuite les patchs qui permettront au module de fonctionner effectivement. Dès que le module aura été repris en main et que sa compatibilité aura été officialisée, il sera automatiquement retiré de Lenient et repassera pas le système original.

Utiliser Lenient pour votre mise à jour

Pour exploiter le potentiel de ce nouveau point d'entrée, vous devez utiliser composer 2 et mettre à jour votre composer.json en y ajoutant le nouveau repository avant le gestionnaire habituel de drupal.org.

Par exemple, si votre composer.json ressemble à ça (si vous vous demandez ce qu'est ce repository "assets" je vous invite à lire notre article sur la gestion des librairies front via composer) :

    "repositories": {
        "assets": {
            "type": "composer",
            "url": "https://asset-packagist.org"
        },
        "drupal": {
            "type": "composer",
            "url": "https://packages.drupal.org/8"
        }
    }

Il faut le transformer pour qu'il ressemble à ça :

    "repositories": {
        "assets": {
            "type": "composer",
            "url": "https://asset-packagist.org"
        },
        "lenient": {
            "type": "composer",
            "url": "https://packages.drupal.org/lenient"
        },
        "drupal": {
            "type": "composer",
            "url": "https://packages.drupal.org/8"
        }
    }

Ce nouveau repository prendra la priorité sur l'ancien pour tous les modules et thèmes n'étant pas encore officiellement portés et retirera leur dépendance au cœur (et uniquement au cœur) pour débloquer votre processus de mise à jour via composer. Cependant, pour que votre dépendance puisse être utilisée dans Drupal il est nécessaire que les changements soient appliqués au code. Bien heureusement il est aussi possible de le faire via composer et ce relativement facilement ! Je vous invite à consulter cet article d'un de nos confrères de la communauté Drupal française qui vous expliquera comment utiliser composer pour appliquer un ou plusieurs patchs sur vos dépendances.

Catégories
Drupal
Drupal 8
Drupal 9
Tags
composer
upgrade
Par Artusamak
Julien Dubois

Charger vos librairies front via composer

Charger vos librairies front via composer
DuaelFr
lun 04/10/2021 - 15:00

De nombreux modules requièrent des librairies front externes pour fonctionner correctement. Plutôt que les charger manuellement, cet article explique comment les gérer via composer.







Corps

Depuis la sortie de Drupal 8, composer est devenu la façon la plus répandue de gérer les dépendances des projets. Ainsi, nous pouvons charger modules contribués et thèmes de façon unifiée ainsi que, si nécessaire, les librairies PHP dont ils dépendent. Cependant, certains modules ont besoin de librairies venant du monde du front et n'étant pas nativement supportées par composer. Ainsi, pour chacun de ces modules, il est nécessaire d'aller télécharger la librairie manuellement et de l'ajouter dans son dépôt de code. Il faut ensuite suivre régulièrement les mises à jour de toutes les librairies de tous les projets et les télécharger de nouveau en cas d'évolution ou de faille de sécurité.

Ça, c'était avant.

Cela fait bien longtemps maintenant que cette problématique a été résolue par les personnes travaillant sur le front des projets via divers package managers comme npm et bower, dont composer est d'ailleurs inspiré. Mais alors, pourquoi est-ce si compliqué de gérer ces librairies dans Drupal ?

npm, bower et composer ne référencent pas les mêmes types de paquets. En effet, les paquets PHP n'ont pas la même organisation et le même usage que les paquets Javascript. Cependant, même s'il est techniquement possible de déclarer un paquet Javascript dans packagist (la base de données alimentant composer), les auteurs de ces paquets ne le font généralement pas pour ne pas avoir à gérer tous les gestionnaires de paquets du monde et parce que cela n'est généralement pas pertinent pour l'usage que l'on peut faire de leur outil. Les personnes maintenant des outils Javascript se concentrent donc sur npm et bower, les deux plus utilisés.

Bienvenue Asset Packagist

La communauté étant pleine de ressources, le projet Asset Packagist a émergé pour répondre à ce besoin. Son but, mettre à disposition les paquets présents sur npm et bower via composer à moindre effort. Ainsi, il est possible de récupérer ces dépendances et de les maintenir à jour de la même façon que le reste de nos modules.

composer étant configuré pour uniquement chercher ses paquets sur son propre packagist, nous allons devoir tout de même procéder à quelques configurations dans notre projet pour pouvoir utiliser Asset Packagist comme source, suivez le guide !

Configurer le repository

Comme lorsque l'on souhaite pouvoir récupérer les modules et thèmes de Drupal, nous devons déclarer un repository spécifique au sein de notre fichier composer.json. Voilà à quoi ressemble la section repositories de mon fichier :

    "repositories": {
        "drupal": {
            "type": "composer",
            "url": "https://packages.drupal.org/8"
        },
        "assets": {
            "type": "composer",
            "url": "https://asset-packagist.org"
        }
    },

Désormais, vous avez la possibilité de récupérer les dépendances front de vos modules via les commandes composer require npm-asset/PAQUET ou composer require bower-asset/PAQUET en cherchant sur le site d'Asset Packagist le nom correspondant.

Cependant, en l'état nos dépendances seront installées dans le dossier /vendor, comme les dépendances PHP, ce qui ne nous arrange pas puisque les modules les chercheront dans le dossier /libraries pour les rendre accessibles aux visiteurs.

Configurer l'emplacement des librairies

Pour faire en sorte que composer place les fichiers à l'endroit voulu, il nous faut exploiter les possibilités offertes par le paquet composer/installers. Si ce dernier n'est pas déjà installé dans votre projet (ce qui est peu probable si vous gérez vos modules via composer), il vous suffit de taper la commande composer require composer/installers pour ajouter la dépendance.

Ensuite, il faut ajouter quelques informations dans la section extra de votre composer.json.

  • L'entrée installer-types permet de déclarer les types de paquets en provenance de Asset Packagist.
  • L'entrée installer-paths permet de déterminer l'endroit où chaque type de paquet sera déposé. Dans le code ci-dessous, les déclarations ont été ajoutées à celles de Drupal.
    "extra": {
        "installer-types": ["bower-asset", "npm-asset"],
        "installer-paths": {
            "web/core": ["type:drupal-core"],
            "web/libraries/{$name}": [
                "type:drupal-library",
                "type:bower-asset",
                "type:npm-asset"
            ],
            "web/modules/contrib/{$name}": ["type:drupal-module"],
            "web/profiles/contrib/{$name}": ["type:drupal-profile"],
            "web/themes/contrib/{$name}": ["type:drupal-theme"],
            "drush/Commands/contrib/{$name}": ["type:drupal-drush"],
            "web/modules/custom/{$name}": ["type:drupal-custom-module"],
            "web/themes/custom/{$name}": ["type:drupal-custom-theme"]
        },
    }

Et voilà, votre projet est prêt à recevoir ces dépendances et à les maintenir à jour suivant le même processus que vos modules et vos thèmes !

Catégories
Drupal
Drupal 10
Drupal 8
Drupal 9
Tags
composer
libraries
Par Christophe MOLLET
Christophe Mollet

Quel CMS choisir entre Wordpress et Drupal ?

Si vous souhaitez créer un site internet, il est important de bien évaluer vos besoins et vos objectifs afin de choisir, par la suite, le CMS le plus adapté à votre projet. Afin de vous aider à y voir plus clair, notre agence web vous présente, dans cet article, les 2 CMS les plus populaires, à savoir : Wordpress et Drupal.

Par Artusamak
Julien Dubois

Avez-vous anticipé la fin de vie de Drupal 7 et 8 ?

Avez-vous anticipé la fin de vie de Drupal 7 et 8 ?
stephanie@happyculture.coop
lun 02/08/2021 - 17:24

Alors que Drupal 8 cèdera sa place à Drupal 9 cette année, Drupal 7 quant à lui reste en sursis jusqu’en novembre 2022.
Alors n’attendez plus, passez à Drupal 9 !




Migrer de Drupal 7 ou 8 à Drupal 9
Corps

Que se passe-t-il ?

Dès 2019, la date de fin de vie de Drupal 7 et Drupal 8 a été annoncée. Ce sera pour le mois de novembre 2021.

La règle dans la communauté Drupal c’est 2 versions majeures maintenues en simultané (Drupal 7 et Drupal 8 à l’époque). L’arrivée de Drupal 9 devait pousser Drupal 7 vers la retraite mais papy fait de la résistance !

En effet, son utilisation importante chez de nombreux utilisateurs finaux, la migration complexe vers Drupal 8 et le COVID ont repoussé son arrêt de carrière de 12 mois, il jouera donc les prolongations jusqu’en novembre 2022

De son côté, Drupal 8 est toujours rangé au placard à la date prévue car c’est sa dépendance à Symfony 3 qui arrive en fin de vie et qui lui fera quitter les projecteurs en novembre 2021.


Drupal release cycle
@hugovk

 

Quels sont les risques ?

Avec le retrait de ces deux versions, votre système de gestion de contenu ne va pas arrêter de fonctionner du jour au lendemain.

Ce que signifie leur fin de vie c’est que les équipes officielles qui s’occupent de maintenir le logiciel ne le feront plus. Il n’y aura donc plus de mises à jour de correctif ou de sécurité. Votre site ne bénéficiera plus de la protection offerte par l’équipe de sécurité de drupal.org. Elle s’assure que tous les modules, thèmes, distributions et le cœur de Drupal sont sécurisés. Qu’aucune faille ne peut être exploitée par des pirates et le cas échéant, produit des patchs de sécurité pour que vous puissiez mettre à jour vos sites en toute sérénité. C’est cette partie là qui s’arrête au mois de novembre 2021 pour Drupal 8.

 

Que dois-je faire ?

Selon vos sites, vous êtes dans l’une des deux situations suivantes :

Mon site est sous Drupal 7

D’ici au mois de novembre 2022, vous devez lancer le chantier de montée de version de votre site. Vers Drupal 9 ou vers un autre CMS, vous devez vous posez la question de l’impact de cette échéance.
À l’instar de Drupal 6, quelques grosses sociétés expertes Drupal ont annoncé qu’elles contribueraient à la maintenance de correctifs de sécurité de Drupal 7. Si une faille de sécurité importante venait à être découverte, ils s’engagent à reverser à la communauté le patch de sécurité aussitôt qu’il sera disponible.
Bien que cela soit une bonne nouvelle, ils ne maintiendront pas tout l’écosystème des modules utilisés par Drupal 7. Vous devez tenir compte de cette échéance pour gérer la montée de version de votre site.

Si votre site n’est plus dynamique, vous pouvez envisager une statification pour ne pas vous engager dans une refonte.

Il vous reste 16 mois pour agir, la durée moyenne d’un projet de refonte est de plusieurs mois. Ne traînez pas, nous pouvons vous aider !

Mon site est sous Drupal 8

Si votre site est sous Drupal 8, l’échéance est dans 4 mois mais, la bonne nouvelle c’est que la route est bien plus droite. En effet, le principal reproche fait à Drupal 6 et 7 était la complexité des montées de versions majeures. Comme nous l’avons indiqué précédemment, passer de Drupal 7 à Drupal 9 est un coût non négligeable. Ce frein a été entendu par la communauté et la gestion des montées de version a été revue pour en tenir compte. Depuis Drupal 8, la montée de version est sans friction car pour peu que vous mainteniez votre site Drupal 8 à jour, le passage à Drupal 9 consiste à simplement retirer le code déprécié entre les deux versions. Ce qui est une quantité bien moindre que précédemment.

Le coût de la montée de version est donc quasiment le même que celui d’une montée intermédiaire. On parle de quelques jours tout au plus contre des semaines voire des mois précédemment (car on en profitait en général pour changer bien d’autres choses par la même occasion).

Votre équipe technique devra donc s’occuper de cela et ne devrait pas avoir de problèmes pour gérer cette montée de version. Les quelques freins qui peuvent exister étant des modules contribués non compatibles avec Drupal 9 mais ils sont minoritaires. 100% du top 200 des modules et 95% du top 1000 est compatible avec Drupal 9.

Vous souhaitez en savoir plus ? Vous souhaitez migrer votre site vers Drupal 9 ?
Contactez-nous !

Catégories
Drupal
Drupal 7
Drupal 8
Drupal 9
Tags
Drupal
Par Christophe MOLLET
Christophe Mollet

Les 10 modules Drupal 9 indispensables

Drupal possède déjà de nombreux modules de base, appelés module du cœur, extrêmement puissants et efficaces pour la construction de votre site web. Étant également un CMS très modulable et pouvant être personnalisé selon les besoins de chaque projet, il est important de connaître certains modules de la communauté, appelés module contrib, indispensables peu importe votre domaine. Un de nos experts Drupal vous présente, dans cet article, son TOP 10 des modules Drupal 9 les plus indispensables.

Pages