Tutorials Ibexa
le jeudi 7 octobre 2021

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+)

 

//src/Provider/RelatedVariableProvider.php

<?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 :

//config/package/template_rules.yaml

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 :

 

//src/Provider/RelatedVariableProvider.php

<?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 :

 

//config/package/template_rules.yaml

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 :

 

//src/Provider/RelatedParameterProvider.php

<?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 :

 

//config/packages/template_rules.yaml

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):

 

//config/services.yaml

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