Comment définir un champ étendu ? À partir de la version 2023.1.1

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 type docid ou account.
  • 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 :

Comment définir un paramètre de Smart Structure ?