À partir de la version 2023.1.1
Comment définir un champ étendu ?Un Extended Smart Field, aussi appelé champ étendu, est un type de Smart Field permettant recopier dynamiquement la valeur d'un champ d'un Smart Element donné.
Recommandation
Si vous n’êtes pas familier avec les champs étendus et leur fonctionnement, il est fortement recommandé de lire la documentation associée.
Prérequis
Afin de pouvoir suivre ce guide, il faut préalablement avoir créé une ou plusieurs Smart Structure(s). Il est également recommandé d'avoir défini un champ calculé sur l'une d'entre elle pour comprendre les enjeux de ce chapitre.
Prérequis techniques
- Anakeen Platform 4 - 2023
Il est recommandé, mais pas nécessaire, d'ajouter le module @anakeen/workers
à votre projet ainsi que d'activer
l'extension de développement workers
dont la mise en place est détaillée dans ce guide. Il
nous suffira d'activer la fonctionnalité ExtendedSmartField.
Ajouter un champ étendu
Reprenons l'exemple de la Smart Structure MENU
. Notre menu se compose d'une liste de PLAT
et de BOISSON
. Nous
avons vu comment calculer le prix total du menu automatiquement. Cependant, ce calcul n'a lieu qu'après une modification
du menu. Ainsi, lorsque le prix d'un plat ou d'une boisson change, le prix total n'est pas recalculé tant que le menu
n'a pas été édité.
Une solution possible est apportée par les champs étendus.
Un extended-smart-field
est une copie dynamique de la valeur d'un champ d'un Smart Element. Ajoutons deux champs
étendus qui recopieront le prix des plats et boissons référencés.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<smart:config xmlns:smart="https://platform.anakeen.com/4/schemas/smart/1.0">
<smart:structure-configuration name="MENU" label="Menu">
<smart:icon file="menu.png"/>
<smart:class>Cogip\Restauratec\SmartStructures\Menu\MenuBehavior</smart:class>
<smart:fields>
<smart:field-set name="menu_frame" type="frame" access="ReadWrite" label="Informations relatives au menu">
<smart:field-text name="menu_title" needed="true" is-title="true" access="ReadWrite" label="Libellé"/>
<smart:field-htmltext name="menu_description" access="ReadWrite" label="Description"/>
<smart:field-set name="menu_composition" type="array" access="ReadWrite" label="Composition du menu">
<smart:field-docid access="ReadWrite" name="menu_plat" label="Plat" relation="PLAT"/>
<smart:extended-field-money name="menu_plat_price" access="Read" label="Prix du plat" >
<smart:copy relation-field="menu_plat" from-field="consommable_price_excl_vat" />
</smart:extended-field-money>
<smart:field-docid access="ReadWrite" name="menu_boisson" label="Boisson" relation="BOISSON"/>
<smart:extended-field-money name="menu_boisson_price" access="Read" label="Prix de la boisson" >
<smart:copy relation-field="menu_boisson" from-field="consommable_price_excl_vat" />
</smart:extended-field-money>
</smart:field-set>
<smart:field-double name="menu_discount" access="ReadWrite" label="Remise applicable (%)"/>
<smart:field-money name="menu_price" access="Read" label="Prix (€)"/>
</smart:field-set>
</smart:fields>
<smart:hooks>
<smart:field-hook event="onPreRefresh" field="menu_price">
<smart:field-callable function="::calculateTotalPrice"/>
</smart:field-hook>
</smart:hooks>
<smart:defaults/>
</smart:structure-configuration>
</smart:config>
Informations
relation_field
indique dans quel champ récupérer l'identifiant du document à recopier, il pointe donc toujours vers un champ de typedocid
ouaccount
.from_field
indique le nom du champ à recopier.
Notre Smart Structure MENU
possède désormais deux nouveaux champs menu_plat_price
et menu_boisson_price
contenant
respectivement les prix de tous les plats/boissons du menu. Si le prix d'un consommable référencé change, son prix est
mis à jour dans chacun des menus le référençant et cette mise à jour relance également le calcul des champs calculés.
Garanties
Le prix total affiché est toujours à jour.
Nous pouvons également simplifier la fonction de calcul du prix total du menu :
<?php
namespace Cogip\Restauratec\SmartStructures\Menu;
use SmartStructure\Fields\Menu as MenuFields;
use Anakeen\SmartHooks;
class MenuBehavior extends \Anakeen\SmartElement
{
public function registerHooks()
{
parent::registerHooks();
}
public function calculateTotalPrice(): float
{
$consumables_prices = array_merge(
array_values($this->getAttributeValue(MenuFields::menu_plat_price)),
array_values($this->getAttributeValue(MenuFields::menu_boisson_price))
);
$discount = $this->getAttributeValue(MenuFields::menu_discount);
$totalPrice = 0;
foreach ($consumables_prices as $price) {
if ($price !== null) {
$totalPrice += $price;
}
}
return $totalPrice * (1 - $discount / 100);
}
}
Attention
Pensez à déployer vos modifications.
make deploy
Résultat / Vérification
Modifions le prix d'un plat et affichons le menu le référençant : le prix du plat est à jour et le prix total est cohérent.
Personnaliser la mise à jour
Il est possible de personnaliser la mise à jour d'un champ étendu. Supposons que notre Smart Structure MENU
suive un
cycle de vie à trois états :
- Brouillon
- Créé
- Publié
Informations
Veuillez vous référer au guide de création d'un cycle de vie.
Lorsqu'un menu passe à l'état Publié, nous voulons figer les prix des consommables référencés. Il faut pour cela
empêcher la mise à jour des champs étendus menu_plat_price
et menu_boisson_price
.
Le traitement d'une mise à jour correspond au déclenchement du Smart Hook UPDATEESF
, il suffit donc de remplacer sa
fonction de callback pour ignorer les demandes de mises à jour sur un menu publié.
<?php
namespace Cogip\Restauratec\SmartStructures\Menu;
use SmartStructure\Fields\Menu as MenuFields;
use Anakeen\SmartHooks;
class MenuBehavior extends \Anakeen\SmartElement
{
public function registerHooks()
{
parent::registerHooks();
$this->getHooks()->removeListeners(SmartHooks::UPDATEESF);
$this->getHooks()->addListener(
SmartHooks::UPDATEESF,
function (string $smartField, int $publisherSmartElementId, int $index = -1, bool $nostore = false) {
if ($this->state === 'PUBLIE') {
return "";
}
return $this->updateExtendedSmartField($smartField, $publisherSmartElementId, $index, $nostore);
}
);
}
}
public function calculateTotalPrice(): float
{
$consumables_prices = array_merge(
array_values($this->getAttributeValue(MenuFields::menu_plat_price)),
array_values($this->getAttributeValue(MenuFields::menu_boisson_price))
);
$discount = $this->getAttributeValue(MenuFields::menu_discount);
$totalPrice = 0;
foreach ($consumables_prices as $price) {
if ($price !== null) {
$totalPrice += $price;
}
}
return $totalPrice * (1 - $discount / 100);
}
}
Et ensuite ?
Continuons sur la gestion des champs de notre Smart Structure au travers du guide :