Skip to content
Snippets Groups Projects
Commit 5d3b294a authored by Laurent Lecluse's avatar Laurent Lecluse
Browse files

Ajout des triggers

parent d97686f3
No related branches found
No related tags found
No related merge requests found
Pipeline #19356 passed
......@@ -82,6 +82,6 @@ unicaenVue.axios.get(
});
```
Lorsqu'il reçoit une réponse du serveur, si cette dernière comporte des messages issus du flashMessenger, il va les afficher sous formes d'alertes.
Les alertes sont personnalisées selon qu'il s'agit de success, warning, info ou error. Elles sont affichées pendant 5 secondes, sauf les erreurs qu'il faut fermer
Lorsqu'il reçoit une réponse du serveur, si cette dernière comporte des messages issus du flashMessenger, il va les afficher sous formes de toasts.
Les toasts sont personnalisées selon qu'il s'agit de success, warning, info ou error. Ils sont affichés pendant 3 secondes, sauf les erreurs qu'il faut fermer
manuellement afin d'avoir le temps de lire le message et de le traiter.
......@@ -112,6 +112,11 @@ Ce dernier va :
- collecter les éventuels messages issus du `flashMessenger`
- convertir le tout en Json pour envoi au client
AxiosModel peut prendre en construction kjusqu'à 3 paramètres :
1. Les données en tant que telles
2. Les prioriétés (utiles seulement si on traite des objets et facultatives si on transmet des objets implémentant AxiosInterface)
3. Les triggers (si nécessaire). Vous trouverez [plus d'infos sur les triggers ici](#les-triggers).
Voici un exemple d'action de contrôleur qui envoie des données au client en mode Ajax vers Axios :
```php
......@@ -133,6 +138,7 @@ use UnicaenVue\View\Model\AxiosModel;
$this->flashMessenger()->addSuccessMessage('Tout va bien!');
// Et on retourne un AxiosModel qui présente le tout au client
// Ici, nous traitons un tableau en entrée, donc pas besoin de préciser des propriétés à extraire et nous n'avons pas besoin de triggers
return new AxiosModel($contacts[$monId]);
// Si on exporte un objet ou un tableau d'objets, on peut aussi fournir une lisye de propriétés, cf. ExiosExtractor
......@@ -361,6 +367,85 @@ var_dump($extracted);
// 'ville' => string 'Caen' (length=4)
```
#### Les triggers
Il est possible de transformer les données traitées via Axios au moyen de triggers.
Ce sera utile si, par exemple, on veut ajouter des propriétés à la volée à un objet qui n'en était pas pourvu ou si on veut modifier
après coup la valeur de certaines données.
Il s'agit d'un usage avancé du dispositif.
Les triggers sont un tableau de fonctions dont les clés sont les chemins qui vont permettre de déterminer sur quelles données nous
voudrons agir, et les valeurs sont des fonctions anonymes dotées de deux paramètres $original : les données originales, c'est-à-dire avant extractions et $extracted, c'est-à-dire le résultat extrait de l'original.
La fonction anonyme devra renvoyer un résultat qui remplacera $extracted dans l'arborescence finale.
Les chemins sont définis de la manière suivante :
* Si on a une liste d'objets, alors `'/'` permettra d'atteindre chaque occurence du tableau renvoyé.
* Si on y ajoute `[]`, ce qui donnera `'/[]'`, alors on pourra agir sur tout le tableau de données (à condition toutefois que ce soit bien une liste de données qu'on manipule).
* Si on veut accéder à des données plus en avant dans l'arborescence, alors on la parcourera avec des slashs `/``, comme des répertoires.
Exemple de chemin plus complexe : prenons la structure de données citée [ci-dessous](#depuis-doctrine).
Si nous voulons agir sur les créateurs des volumes horaires, il faudra utiliser le chemin suivant :
`/volumesHoraires/histoCreateur`.
Nous pourrons ainsi traiter les créateurs des volumes horaires, et pas les créateurs des missions.
Exemple d'utilisation des triggers :
Prenons la structure de données ci-dessus, à savoir une liste de personnes ayant une adresse.
Voici un exemple de trigger qui va ajouter l'âge aux personnes :
```php
$personnes = [new Personne(), new Personne()];
$properties = ['nom', 'prenom', 'isMajeur', 'adresse'];
$triggers = [
// '/' signifie que nous agirons sur les données de premier niveau, qui sont ici des Personne. Le trigger agira pour chaque personne
'/' => function($original, $extracted){
// $original contiendra l'objet correspondant à l'entité Personne
// $extracted contiendra le tableau de données déjà extrait
$extracted['age'] = 37; // On ajoute ici une propriété en extraction qui n'a pas été générée avant.
// Nous pourrions tout aussi bien retirer une donnée, ou bien en changer le type ou la valeur.
return $extracted;
},
// Autre exemple de trigger qui agira non plus sur chaque personne de la liste, mais sur l'ensemble de la liste
'/[]' => function($original, $extracted){
// $original contient la liste des objets Personne
// $extracted contient un tableau des deux personnes converties en array
unset($extracted[0]);// on supprime la première personne de la liste
// il est obligatoire de retourner quelque chose
return $extracted;
},
// Encore un autre exemple : on va agir sur les adresses de chaques personnes
'/adresse' => function($original, $extracted){
$extracted['pays'] = 'France';
return $extracted;
}
];
$extracted = \UnicaenVue\Axios\AxiosExtractor::extract($personnes,$properties,$triggers);
var_dump($extracted);
// Renvoie :
// array (size=4)
// 'nom' => string 'Dupont' (length=6)
// 'prenom' => string 'Robert' (length=6)
// 'isMajeur' => boolean true
// 'adresse' => array (size=2)
// 'cp' => int 14000
// 'ville' => string 'Caen' (length=4)
```
### Depuis Doctrine
Axios peut également prendre en entrée des requêtes Doctrine `Doctrine\ORM\Query`.
......
......@@ -9,36 +9,49 @@ class AxiosExtractor
{
const DATETIME_FORMAT = 'Y-m-d\TH:i:s.u\Z'; // timestamp ISO 8601 pour HTML5
protected array $triggers = [];
public static function extract($data, array $properties = [])
public static function extract($data, array $properties = [], array $triggers = [])
{
$axios = new self;
$axios->triggers = $triggers;
return $axios->extractData($data, $properties);
}
public function extractData($data, array $properties = [])
protected function extractData($data, array $properties = [], string $path = '')
{
$triggerPath = $path ? $path : '/';
if ($data instanceof Query) {
return $this->extractData($data->getResult(), $properties);
$result = $this->extractData($data->getResult(), $properties, '');
} elseif ($this->isList($data)) {
return $this->extractList($data, $properties);
$result = $this->extractList($data, $properties, $path);
$triggerPath .= '[]';
} elseif (is_array($data)) {
return $this->extractArray($data, $properties);
$result = $this->extractArray($data, $properties, $path);
} elseif ($data instanceof \DateTime) {
return $data->format(self::DATETIME_FORMAT);
$result = $data->format(self::DATETIME_FORMAT);
} elseif (is_object($data)) {
return $this->extractObject($data, $properties);
$result = $this->extractObject($data, $properties, $path);
} else {
return $data;
$result = $data;
}
if (array_key_exists($triggerPath, $this->triggers) && !$data instanceof Query){
// trigger est un callable qui accepte deux arguments : le premier les la donnée originale, le second la donnée extraite
// il doit retourner une donnée qui remplacera la donnée extraite
$result = $this->triggers[$triggerPath]($data, $result);
}
return $result;
}
protected function extractObject($data, array $properties): array
protected function extractObject($data, array $properties, string $path = ''): array
{
$result = [];
......@@ -81,7 +94,7 @@ class AxiosExtractor
foreach ($methods as $method) {
if (method_exists($data, $method)) {
$value = $data->$method();
$result[$property] = $this->extractData($value, $subProperties);
$result[$property] = $this->extractData($value, $subProperties, $path.'/'.$property);
break;
}
}
......@@ -97,7 +110,7 @@ class AxiosExtractor
protected function extractArray(array $data, array $properties): array
protected function extractArray(array $data, array $properties, string $path = ''): array
{
$result = [];
......@@ -121,7 +134,7 @@ class AxiosExtractor
}
if (array_key_exists($property, $data)) {
$result[$property] = $this->extractData($data[$property], $subProperties);
$result[$property] = $this->extractData($data[$property], $subProperties, $path.'/'.$property);
}
}
......@@ -130,11 +143,11 @@ class AxiosExtractor
protected function extractList($list, array $properties = []): array
protected function extractList($list, array $properties = [], string $path = ''): array
{
$result = [];
foreach ($list as $sobj) {
$result[] = $this->extractData($sobj, $properties);
$result[] = $this->extractData($sobj, $properties, $path);
}
return $result;
......
......@@ -12,12 +12,15 @@ class AxiosModel implements ModelInterface
protected array $properties = [];
protected array $triggers = [];
public function __construct($data, array $properties = [])
public function __construct($data, array $properties = [], array $triggers = [])
{
$this->data = $data;
$this->properties = $properties;
$this->triggers = $triggers;
}
......@@ -54,6 +57,22 @@ class AxiosModel implements ModelInterface
public function getTriggers(): array
{
return $this->triggers;
}
public function setTriggers(array $triggers): AxiosModel
{
$this->triggers = $triggers;
return $this;
}
public function getVariables()
{
return $this->data;
......
......@@ -33,7 +33,7 @@ class AxiosRenderer extends JsonRenderer
protected function makeData(AxiosModel $axiosModel): array
{
$data = AxiosExtractor::extract($axiosModel->getData(), $axiosModel->getProperties());
$data = AxiosExtractor::extract($axiosModel->getData(), $axiosModel->getProperties(), $axiosModel->getTriggers());
$namespaces = [
$this->flashMessenger::NAMESPACE_SUCCESS,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment