# Mapping Dolibarr - React Pour exposer les objets Dolibarr vers l'application React, SmartMaker utilise des classes de mapping (préfixées ''dm''). ## Principe Les classes ''dm*'' transforment les objets Dolibarr en JSON optimisé pour React : * Renommage des champs (''nom'' → ''name'') * Résolution des clés étrangères (''fk_pays'' → nom du pays) * Transformation de données (logo fichier → base64) * Filtrage des champs exposés ## Créer une classe de mapping ### Structure de base ``` clé React protected $listOfPublishedFields = [ 'rowid' => 'id', 'ref' => 'ref', 'label' => 'label', 'description' => 'description', 'fk_soc' => 'thirdparty', 'fk_statut' => 'status', 'date_creation' => 'created_at', 'note_public' => 'public_note', 'note_private' => 'private_note', ]; public function __construct() { global $langs; // Charger les traductions $langs->load("mymodule@mymodule"); // Initialiser le mapping $this->boot(); } } ``` ### Mapping des champs La variable ''listOfPublishedFields'' définit quels champs sont exposés : ``` protected $listOfPublishedFields = [ // Champs simples 'rowid' => 'id', // rowid devient id 'nom' => 'name', // nom devient name 'address' => 'address', // même nom // Clés étrangères (résolues automatiquement) 'fk_soc' => 'thirdparty', // ID → objet société 'fk_pays' => 'country', // ID → nom du pays 'fk_departement'=> 'department', // ID → nom département // Extrafields 'options_myfield' => 'my_field', ]; ``` ### Override de types Pour modifier le type d'un champ : ``` protected $parentFieldsOverride = [ 'duree' => ['type' => 'duration', 'required' => 'required'], 'contacts' => ['type' => 'array'], 'status' => ['type' => 'select'], ]; ``` ## Filtrer les valeurs ### Fonction magique fieldFilterValueXXX Pour transformer une valeur avant l'envoi, créez une méthode ''fieldFilterValueXXX'' où XXX est le nom du champ (première lettre en majuscule) : ``` /** * Transformer le logo en base64 */ public function fieldFilterValueLogo($object) { global $conf; $dir = $conf->societe->multidir_output[$object->entity]; $logoPath = $dir . "/" . $object->id . "/logos/" . $object->logo; if (!file_exists($logoPath)) { return null; } $type = pathinfo($logoPath, PATHINFO_EXTENSION); return 'data:image/' . $type . ';base64,' . base64_encode(file_get_contents($logoPath)); } /** * Formater une date */ public function fieldFilterValueDateCreation($object) { return dol_print_date($object->date_creation, 'daytext'); } /** * Récupérer les contacts associés */ public function fieldFilterValueContacts($object) { return $object->liste_contact(-1, 'external'); } /** * Ajouter des photos liées */ public function fieldFilterValuePhotos($object) { global $conf; $photos = []; $dir = $conf->mymodule->dir_output . '/' . $object->ref; if (is_dir($dir)) { $files = scandir($dir); foreach ($files as $file) { if (preg_match('/\.(jpg|jpeg|png)$/i', $file)) { $path = $dir . '/' . $file; $type = pathinfo($path, PATHINFO_EXTENSION); $photos[] = [ 'title' => $file, 'src' => 'data:image/' . $type . ';base64,' . base64_encode(file_get_contents($path)) ]; } } } return $photos; } ``` ## Objets avec lignes Pour les objets composés de lignes (factures, commandes, etc.) : ### Configuration ``` // Classe des lignes Dolibarr protected $parentClassNameForLines = 'MyObjectLine'; // Description des champs de lignes (pour générer le formulaire) protected $parentFieldsForLines = [ 'id' => ['type' => 'integer', 'label' => 'ID', 'visible' => -1], 'date' => ['type' => 'datetime', 'label' => 'Date', 'visible' => 1], 'desc' => ['type' => 'html', 'label' => 'Description', 'visible' => 1], 'qty' => ['type' => 'integer', 'label' => 'Quantity', 'visible' => 1], ]; // Mapping des champs de lignes protected $listOfPublishedFieldsForLines = [ 'id' => 'id', 'date' => 'date', 'desc' => 'description', 'qty' => 'quantity', 'subprice' => 'unit_price', 'total_ht' => 'total', ]; // Titre affiché au-dessus des lignes protected $parentLabelForLines = "linesDetail"; ``` ### Exemple complet (Intervention) ``` ['type' => 'integer', 'label' => 'ID'], 'date' => ['type' => 'datetime', 'label' => 'Date'], 'duration' => ['type' => 'duration', 'label' => 'Duration'], 'desc' => ['type' => 'html', 'label' => 'Description'], ]; protected $listOfPublishedFields = [ 'rowid' => 'id', 'fk_soc' => 'thirdparty', 'ref' => 'ref', 'ref_client' => 'customer_ref', 'duree' => 'duration', 'description' => 'description', 'fk_statut' => 'status', 'contacts' => 'contacts', // Extrafields 'options_smartinterventions_address' => 'intervention_address', 'options_smartinterventions_date_inter' => 'date_intervention', ]; protected $listOfPublishedFieldsForLines = [ 'id' => 'id', 'date' => 'date', 'duration' => 'duration', 'desc' => 'description', ]; protected $parentLabelForLines = "linesHistory"; protected $parentFieldsOverride = [ 'duree' => ['type' => 'duration'], 'contacts' => ['type' => 'array'], ]; public function __construct() { global $langs; $langs->load("smartinterventions@smartinterventions"); $this->boot(); } } ``` ## Utilisation dans un Controller ``` public function show($payload = null) { global $db; $id = $payload['id']; // Charger l'objet Dolibarr $object = new \MyObject($db); $object->fetch($id); $object->fetch_optionals(); // Extrafields $object->fetch_lines(); // Lignes (si applicable) // Mapper pour React $mapping = new dmMyObject(); $data = $mapping->exportMappedData($object); return [$data, 200]; } ``` ## Extrafields dynamiques Pour ajouter des extrafields configurables : ``` public function __construct() { global $conf, $langs; $langs->load("mymodule@mymodule"); // Ajouter les extrafields depuis la configuration du module $extrafields = getDolGlobalString('MYMODULE_EXTRAFIELDS_LIST'); if (!empty($extrafields)) { foreach (explode(',', $extrafields) as $field) { $key = "options_" . $field; $this->listOfPublishedFields[$key] = $key; } } $this->boot(); } ``` ## Voir aussi * [[start|Back (PHP)]] - Routes et Controllers * [[../front/requetes_api|Requêtes API]] - Côté React * [[../smartauth/start|SmartAuth]] - Classes dm* du coeur Dolibarr