File_history est un module Drupal développé par Eurelis pour les besoins d’un projet et diffusé officiellement à la communauté depuis février 2018.
Ce module, maintenu régulièrement, propose un nouveau type champ pour la Form API Drupal, ajoutant un certain nombre de fonctionnalités au champ de téléversement classique. La version 2, disponible depuis février dernier, étant ce type de champs en un widget utilisable dans la configuration des entités.

Les principales fonctionnalités proposées par ce nouveau type de champs sont :

  • Permettre une validation des fichiers lors du téléversement
  • Permettre de visualiser l’historique des fichiers téléversés dans ce champ
  • Choisir parmis les fichiers téléversés celui à utiliser
  • Fournir une collection de hook afin de modifier le rendu du tableau de fichiers

Aux origines du module

Le besoin initial ayant conduit au développement des fonctionnalités du module est un moteur de recommandation de produits basés sur un arbre de décision enregistré dans une matrice Excel.
Vu la complexité des données et du fichier résultant, il a semblé nécessaire dès le début du projet de conserver un historique des fichiers téléversés pour faciliter le rollback en cas de mise à jour hasardeuse.
Un besoin équivalent sur un autre projet nous a poussé à rationaliser la fonctionnalité de gestion des versions des fichier de données et d’en faire un module indépendant.
Le développement c’est fait à l’origine comme une extension du type de champ « managed_file » fournis par le core Drupal 8. Les stabilisations faisant, le nouveau module s’est dissocié de ce parent pour devenir indépendant, bien qu’il en conserve certaine logiques.

Présentation de l’interface utilisateur

L’interface utilisateur de ce champs reprend l’intégralité des éléments présent dans le besoin d’origine : un champ de téléversement ainsi qu’un tableau des fichiers déjà chargés.
L’interface, qui s'intègre parfaitement dans le back-office Drupal, liste l’ensemble des fichiers préalablement téléversé dans le champs et propose un certain nombre d’opérations sont disponibles pour chaque instance.
La disponibilité des opérations dépend des options qui ont été déclaré lors de l’implémentation du champ.

Implémentation du champ dans la FormApi

Créer un champs de type file_history

L'implémentation de ce type de champs est très proche et étend celle utilisé pour le type de champ managed_file.

A minima, le champ ne demande que les attributs utilisé par managed_file. Un certain nombre de nouveaux attributs sont disponibles.

Dans le cas présenté, une validation spécifique my_custom_validator à été ajouter aux validateurs.

Les attributs no_upload, no_use, no_download permettent d’activer ou non certaines fonctionnalités du tableau correspondant à l’interface utilisateur du champs.

  $validators = [
    'file_validate_extensions' => ['xls xlsx xml txt'],
    'file_validate_size' => [Environment::getUploadMaxSize()],
    'my_custom_validator' => ['paramOne'],
  ];

  $form['configurations_files'] = [
    '#type' => 'file_history',
    '#title' => $this->t('Configurations'),
    '#description' => $this->t('List of files'),
    '#size' => 50,

    // Like Managed Files, general file validation.
    '#upload_validators' => $validators,

    // Folder to store files.
    '#upload_location' => 'public://my_configuration/',

    '#cardinality' => 2,
    '#default_value' => (is_array($default) ? $default : []),

    // Setting an id for the wrapper will activate ajax on buttons.
    '#theme_wrappers' => [
      'form_element' => [
        '#wrapper_attributes' => ['id' => 'change-this-id-wrapper'],
      ],
    ],
  ];

Validation et soumission du champ

Pour la validation et la soumission, la valeur contenu dans le champs est structuré en deux partie.

L’attribut selected contient la liste des fichiers qui ont été marqué comme « sélectionné » dans l’interface utilisateur.

L’attribut in_table contient la liste de toutes les fichiers présents dans la table (sélectionnée ou non).

  public function submitForm(array &$form, FormStateInterface $form_state) {
    parent::submitForm($form, $form_state);

    $value = $form_state->getValue('configurations_files');

    // Do something on submit.
    $selected = $value['selected'];
    $table_state = $value['in_table'];

    $this->config('exemple_file_history.default')
      ->set('selected_configuration_file', $selected)
      ->set('loaded_configuration_file', $table_state)
      ->save();
  }

Implémentation avancée

Le module propose 3 familles de hook_alter.

  • La famille des hook_file_history_headers_alter et hook_file_history_FIELD_ID_headers_alter permettent de modifier les en-têtes de la table.

  • La famille des hook_file_history_rows_alter et hook_file_history_FIELD_ID_rows_alter permettent de modifier le contenu même de la table.

  • La troisième famille est dédié à l’utilisation du champ via le widget et permet d’ajouter des validateur pour l’upload des fichiers. Ce sont les hook_file_history_validator_alter et hook_file_history_FIELD_DEFINITION_ID_validator_alter.

Validation du contenu du fichier pendant le téléversement

Par rapport à la première version, la validation lors de l’upload à été amélioré et se base dorénavant via les validateurs du module file_managed.

Pour cela, la fonction de validation devra posséder une signature répondant au hook_file_validate et ayant comme sortie soir un tableau vide (pas d’erreur lors de la validation) ou un tableau de messages d’erreur.

Conclusion

Ce module, reversé la première fois en février 2018 par Eurelis à la communauté Drupal et maintenu activement depuis est un des témoignage de l'engagement de l'agence sur cette plateforme Open Source.

Depuis plus de 10 ans Eurelis développe une expertise Drupal pointue, et accompagne l'évolution de l'eco-système en contribuant à son enrichissement.

Références:

Vous avez un projet ? Concrétisons vos idées.