vendor/symfony/ux-live-component/src/EventListener/AddLiveAttributesSubscriber.php line 30

Open in your IDE?
  1. <?php
  2. namespace Symfony\UX\LiveComponent\EventListener;
  3. use Psr\Container\ContainerInterface;
  4. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  5. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  6. use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
  7. use Symfony\Contracts\Service\ServiceSubscriberInterface;
  8. use Symfony\UX\LiveComponent\LiveComponentHydrator;
  9. use Symfony\UX\TwigComponent\ComponentAttributes;
  10. use Symfony\UX\TwigComponent\ComponentMetadata;
  11. use Symfony\UX\TwigComponent\EventListener\PreRenderEvent;
  12. use Symfony\UX\TwigComponent\MountedComponent;
  13. use Twig\Environment;
  14. /**
  15.  * @author Kevin Bond <kevinbond@gmail.com>
  16.  *
  17.  * @experimental
  18.  *
  19.  * @internal
  20.  */
  21. final class AddLiveAttributesSubscriber implements EventSubscriberInterfaceServiceSubscriberInterface
  22. {
  23.     public function __construct(private ContainerInterface $container)
  24.     {
  25.     }
  26.     public function onPreRender(PreRenderEvent $event): void
  27.     {
  28.         if (!$event->getMetadata()->get('live'false)) {
  29.             // not a live component, skip
  30.             return;
  31.         }
  32.         if (method_exists($event'isEmbedded') && $event->isEmbedded()) {
  33.             // TODO: remove method_exists once min ux-twig-component version has this method
  34.             throw new \LogicException('Embedded components cannot be live.');
  35.         }
  36.         $metadata $event->getMetadata();
  37.         $attributes $this->getLiveAttributes($event->getMountedComponent(), $metadata);
  38.         $variables $event->getVariables();
  39.         $attributesKey $metadata->getAttributesVar();
  40.         if (isset($variables[$attributesKey]) && $variables[$attributesKey] instanceof ComponentAttributes) {
  41.             // merge with existing attributes if available
  42.             $attributes $attributes->defaults($variables[$attributesKey]->all());
  43.         }
  44.         $variables[$attributesKey] = $attributes;
  45.         $event->setVariables($variables);
  46.     }
  47.     public static function getSubscribedEvents(): array
  48.     {
  49.         return [PreRenderEvent::class => 'onPreRender'];
  50.     }
  51.     public static function getSubscribedServices(): array
  52.     {
  53.         return [
  54.             LiveComponentHydrator::class,
  55.             UrlGeneratorInterface::class,
  56.             Environment::class,
  57.             '?'.CsrfTokenManagerInterface::class,
  58.         ];
  59.     }
  60.     private function getLiveAttributes(MountedComponent $mountedComponentMetadata $metadata): ComponentAttributes
  61.     {
  62.         $name $mounted->getName();
  63.         $url $this->container->get(UrlGeneratorInterface::class)->generate('live_component', ['component' => $name]);
  64.         $data $this->container->get(LiveComponentHydrator::class)->dehydrate($mounted);
  65.         $twig $this->container->get(Environment::class);
  66.         $attributes = [
  67.             'data-controller' => 'live',
  68.             'data-live-url-value' => twig_escape_filter($twig$url'html_attr'),
  69.             'data-live-data-value' => twig_escape_filter($twigjson_encode($data\JSON_THROW_ON_ERROR), 'html_attr'),
  70.         ];
  71.         if ($this->container->has(CsrfTokenManagerInterface::class) && $metadata->get('csrf')) {
  72.             $attributes['data-live-csrf-value'] = $this->container->get(CsrfTokenManagerInterface::class)
  73.                 ->getToken($name)->getValue()
  74.             ;
  75.         }
  76.         return new ComponentAttributes($attributes);
  77.     }
  78. }