Les VariableProvider d'Ibexa 3 , successeurs des ParameterProvider du eZCoreExtraBundle

Tutorials Ibexa

7 oct. 2021

Avant Ibexa 3, un moyen pratique d'injecter des variables dans les templates des vues de contenu était d'utiliser les ParameterProvider du eZCoreExtraBundle. Maintenant, avec Ibexa 3, il est possible de faire la même chose sans avoir besoin d'un bundle tiers.

Premier exemple

Comme exemple, écrivons un VariableProvider qui charge tous les contenus d'un champ liste de relations du contenu affiché. (code pour PHP 7.4+)

 

   

<?php 
declare(strict_types=1); 
namespace App\Provider; 
use ArrayObject;
use eZ\Publish\API\Repository\ContentService;
use eZ\Publish\Core\FieldType\RelationList;
use eZ\Publish\Core\MVC\Symfony\View\ContentView;
use eZ\Publish\Core\MVC\Symfony\View\View;
use eZ\Publish\SPI\MVC\View\VariableProvider; 
class RelatedVariableProvider implements VariableProvider
{
    private ContentService $contentService; 
    public function __construct(ContentService $contentService)
    {
        $this->contentService = $contentService;
    } 
    public function getIdentifier(): string
    {
        // Utilisé dans la configuration
        return 'related';
    } 
    public function getTwigVariables(View $view, array $options = []): object
    {
        /** @var ContentView $view */
        $content = $view->getContent(); 
        /** @var RelationList\Value $value */
        $value = $content->getFieldValue('media'); 
        // La valeur de retour est typée object, donc on retourne un ArrayObject
        return new ArrayObject(array_map(
            fn (int $contentId) => $this->contentService->loadContent($contentId),
            $value->destinationContentIds
        ));
    }
} 
   

Ajoutons la configuration de vue :

   

ezplatform:
  system:
    default:
      content_view:
        full:
          article:
            template: "@ezdesign/content/full/article.html.twig"
            match:
              Identifier\ContentType: article
            params:
              # L'appel au VariableProvider se fait par l'ExpressionLanguage
              medias: '@=twig_variable_provider("related")' 
   

Pour aller plus loin

Ok, mais comment faire si je voulais choisir l'identifiant du champ ? Malheureusement, au contraire des ParameterProvider, il n'est pas possible de passer des options directement (twig_variable_provider n'accepte qu'un seul argument : l'identifiant du provider). Mais, comme le VariableProvider est appelé au travers de l'ExpressionLanguage, nous pouvons appeler une méthode sur la valeur de retour du VariableProvider, avec n'importe quels arguments.

Changeons un peu notre VariableProvider :

 

   

<?php 
declare(strict_types=1); 
namespace App\Provider; 
use eZ\Publish\API\Repository\ContentService;
use eZ\Publish\Core\FieldType\RelationList;
use eZ\Publish\Core\MVC\Symfony\View\ContentView;
use eZ\Publish\Core\MVC\Symfony\View\View;
use eZ\Publish\SPI\MVC\View\VariableProvider; 
class RelatedVariableProvider implements VariableProvider
{
    private ContentService $contentService; 
    public function __construct(ContentService $contentService)
    {
        $this->contentService = $contentService;
    } 
    public function getIdentifier(): string
    {
        return 'related';
    } 
    public function getTwigVariables(View $view, array $options = []): object
    {
        return $this;
    } 
    public function load(View $view, string $fieldIdentifier): array
    {
        /** @var ContentView $view */
        $content = $view->getContent(); 
        /** @var RelationList\Value $value */
        $value = $content->getFieldValue($fieldIdentifier); 
        return array_map(
            fn(int $contentId) => $this->contentService->loadContent($contentId),
            $value->destinationContentIds
        );
    }
} 
   

La méthode getTwigVariables va simplement retourner le provider lui-même, ce qui permet ensuite d'appeler n'importe quelle méthode dans l'expression.

Changeons la configuration de vue en conséquence :

 

   

ezplatform:
  system:
   default:
     content_view:
       full:
         article:
           template: "@ezdesign/content/full/article.html.twig"
           match: Identifier\ContentType: article
           params:
             medias: '@=twig_variable_provider("related").load(view, "media")' 
   

Migrer un ParameterProvider du eZCoreExtraBundle

Voyons à quoi ressemblerait notre exemple précédent en tant que ParameterProvider, et listons les différences :

 

   

<?php 
declare(strict_types=1); 
namespace App\Provider; 
use eZ\Publish\API\Repository\ContentService;
use eZ\Publish\Core\FieldType\RelationList;
use eZ\Publish\Core\MVC\Symfony\View\ContentView;
use Lolautruche\EzCoreExtraBundle\View\ConfigurableView;
use Lolautruche\EzCoreExtraBundle\View\ViewParameterProviderInterface; 
class RelatedParameterProvider implements ViewParameterProviderInterface
{
    private ContentService $contentService; 
    public function __construct(ContentService $contentService)
    {
        $this->contentService = $contentService;
    } 
    public function getViewParameters(ConfigurableView $view, array $options = [])
    {
        /** @var ContentView $view */
        $content = $view->getContent(); 
        /** @var RelationList\Value $value */
        $value = $content->getFieldValue($options['field_identifier']); 
        return array_map(
            fn(int $contentId) => $this->contentService->loadContent($contentId),
            $value->destinationContentIds
        );
    }
} 
   

La configuration de vue :

 

   

ezplatform:
  system:
    default:
      content_view:
        full:
          article:
            template: "@ezdesign/content/full/article.html.twig"
            match: Identifier\ContentType: article
            params:
              medias:
                provider: related
                options:
                  field_identifier: media 
   

Et la configuration du service (en supposant que l'autowiring et l'autoconfiguration sont activées):

 

   

services:
  App\Provider\RelatedParameterProvider:
    tags:
      - { name: "ez_core_extra.view_parameter_provider", alias: "related" } 
   

Pour migrer :

  • supprimer la configuration de service, comme le tag est géré par l'autoconfiguration
  • remplacer ViewParameterProviderInterface par VariableProvider
  • ajouter la méthode getIdentifier
  • ajouter la méthode getTwigVariables qui retournera simplement $this
  • de manière optionnelle, changer le nom ou la signature de la méthode getViewParameters pour mieux correspondre à vos besoins
  • changer la configuration de vue