Personnaliser un export CSV avec Entity Export CSV sur Drupal 8

Container

Le module Entity Export CSV nous permet de mettre en place très rapidement des exports CSV pour n'importe quelle type d'entité de contenu de Drupal 8. Parfois, nous pouvons avoir besoin de personnaliser les exports réalisés, comme exporter 2 informations différentes d'un même champs Entity Reference par exemple. Nous allons découvrir comment procéder pour personnaliser nos exports CSV.

Et parce qu'un bon exemple vaut parfois mieux qu'un long discours, nous allons couvrir ici un besoin spécifique, à titre d'illustration. Depuis une entité de commande de Drupal commerce, nous souhaitons pouvoir exporter le champ Téléphone associé au Profil de facturation. En effet, les entités commande disposent d'un champ Entity Reference Revisions qui référencent le Profil de facturation renseigné lors du tunnel d'achat, et nous souhaitons pouvoir extraire de cette entité Profile un champ particulier, le téléphone.

Dans un premier temps, nous allons altérer les champs récupérés sur l'entité Commande. En effet le module Entity Export CSV dispatche un événement nous permettant d'altérer facilement les champs récupérés sur une entité donnée.

Afin de pouvoir extraire le téléphone nous allons donc ajouter dynamiquement un pseudo champs sur cette entité.

Nous créons un service de type EventSubscriber dans notre module personnalisé my_module, et plus précisement dans le fichier my_module.services.yml.

my_module.entity_export_csv_billing_phone:
  class: Drupal\my_module\EventSubscriber\EntityExportCsvBillingPhoneEventSubscriber
  tags:
    - { name: event_subscriber }

Et notre Class pour altérer les champs disponibles sur l'entité Commande. Cette altération nous permet de pouvoir rajouter autant de pseudo champ que nécessaires.

Ci-dessous notre Class EntityExportCsvBillingPhoneEventSubscriber.

namespace Drupal\my_module\EventSubscriber;

use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\entity_export_csv\Event\EntityExportCsvEvents;
use Drupal\entity_export_csv\Event\EntityExportCsvFieldsSupportedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class EntityExportCsvBillingPhoneEventSubscriber implements EventSubscriberInterface {

  use StringTranslationTrait;

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    $events = [];
    $events[EntityExportCsvEvents::ENTITY_EXPORT_CSV_FIELDS_SUPPORTED] = ['alterFields'];
    return $events;
  }

  /**
   * We want to add a pseudo custom field to export the billing phone field..
   *
   * @param \Drupal\entity_export_csv\Event\EntityExportCsvFieldsSupportedEvent $event
   *   The event.
   */
  public function alterFields(EntityExportCsvFieldsSupportedEvent $event) {
    $entity_type_id = $event->getEntityTypeId();
    if ($entity_type_id === 'commerce_order') {
      $fields = $event->getFields();
      if (isset($fields['billing_profile'])) {
        $fields['billing_phone'] = $fields['billing_profile'];
        $event->setFields($fields);
      }
    }
  }

}

Nous dupliquons ici le champ billing_profile disponible sur l'entité commande pour avoir un nouveau champ billing_phone pour lequel nous pourrons mettre en place un exporter dédié spécifique.

Créons notre Plugin d'export de champ dédié à ce champs (cf. Exporter en CSV les contenus d'un projet Drupal 8).

Dans le répertoire src/Plugin/FieldTypeExport de notre module, nous créons notre Plugin spécifique BillingPhoneExport.

namespace Drupal\my_module\Plugin\FieldTypeExport;

use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\entity_export_csv\Plugin\FieldTypeExportBase;
use Drupal\Core\Field\FieldItemInterface;

/**
 * Defines a billing phone field type export plugin.
 *
 * @FieldTypeExport(
 *   id = "billing_phone_export",
 *   label = @Translation("Billing phone export"),
 *   description = @Translation("Billing phone export"),
 *   weight = 100,
 *   field_type = {
 *     "entity_reference_revisions",
 *   },
 *   entity_type = {
 *    "commerce_order",
 *   },
 *   bundle = {},
 *   field_name = {
 *     "billing_phone",
 *   },
 *   exclusive = FALSE,
 * )
 */
class BillingPhoneExport extends FieldTypeExportBase {

  /**
   * {@inheritdoc}
   */
  public function getSummary() {
    return [
      'message' => [
        '#markup' => $this->t('Billing phone field type exporter.'),
      ],
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function massageExportPropertyValue(FieldItemInterface $field_item, $property_name, FieldDefinitionInterface $field_definition, $options = []) {
    if ($field_item->isEmpty()) {
      return NULL;
    }
    $configuration = $this->getConfiguration();
    if (empty($configuration['format'])) {
      return $field_item->get($property_name)->getValue();
    }

    $field = $configuration['format'];
    if ($field) {
      $entity = $field_item->get('entity')->getValue();
      if ($entity instanceof ContentEntityInterface) {
        if ($entity->hasField($field)) {
          return $entity->{$field}->value;
        }
      }
    }

    return $field_item->get($property_name)->getValue();
  }

  /**
   * {@inheritdoc}
   */
  protected function getFormatExportOptions(FieldDefinitionInterface $field_definition) {
    $options = parent::getFormatExportOptions($field_definition);
    $options['field_phone'] = $this->t('Phone');
    return $options;
  }

}

Notre Plugin d'export de champ déclare dans ses annotations le field_name afin qu'il ne soit disponible que pour le pseudo champ que nous avons créé. Nous utilisons les options du formatage de l'export pour rajouter le champ que nous souhaitons exporter (le cas échéant nous pourrions vouloir par exemple exporter plusieurs champs de l'entité Profile, nous pourrions alors utiliser le même Plugin d'export de champ) puis tout simplement, en nous basant sur le Plugin de base fourni par le module pour les champ Entity Reference (EntityReferenceExport), nous adaptons la méthode massageExportPropertyValue() pour exporter le champs souhaité depuis l'entité Profile.

Et en quelques instants nous disposons alors de la possibilité d'exporter le champ téléphone depuis l'entité Profile reférencée par une commande.

Billing phone export

Nous pouvons alors activer notre nouveau pseudo champ, sélectionner le format d'export spécifique et extraire toutes les données nécessaires au métier.

Ces techniques peuvent être utilisées avec l'aide d'un développeur Drupal 8 pour enrichir les exports de données et les adapter aux besoins métier les plus particuliers, sans avoir à re-développer toute une routine spécifique d'export.

 

Ajouter un commentaire