diff --git a/src/Turbo/CHANGELOG.md b/src/Turbo/CHANGELOG.md index af47f9640d2..f18efbd4940 100644 --- a/src/Turbo/CHANGELOG.md +++ b/src/Turbo/CHANGELOG.md @@ -1,5 +1,29 @@ # CHANGELOG +## 2.1 + +- `TurboStreamResponse` and `AddTurboStreamFormatSubscriber` have been removed, use native content negotiation instead: + + ```php + use Symfony\UX\Turbo\TurboBundle; + + class TaskController extends AbstractController + { + public function new(Request $request): Response + { + // ... + if (TurboBundle::STREAM_FORMAT === $request->getPreferredFormat()) { + $request->setRequestFormat(TurboBundle::STREAM_FORMAT); + $response = $this->render('task/success.stream.html.twig', ['task' => $task]); + } else { + $response = $this->render('task/success.html.twig', ['task' => $task]); + } + + return $response->setVary('Accept'); + } + } + ``` + ## 2.0 - Support for `stimulus` version 2 was removed and support for `@hotwired/stimulus` diff --git a/src/Turbo/README.md b/src/Turbo/README.md index c622e96ce2d..0265fd547d1 100644 --- a/src/Turbo/README.md +++ b/src/Turbo/README.md @@ -295,7 +295,7 @@ namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\UX\Turbo\Stream\TurboStreamResponse; +use Symfony\UX\Turbo\TurboBundle; use App\Entity\Task; class TaskController extends AbstractController @@ -311,9 +311,10 @@ class TaskController extends AbstractController // ... perform some action, such as saving the task to the database // 🔥 The magic happens here! 🔥 - if (TurboStreamResponse::STREAM_FORMAT === $request->getPreferredFormat()) { - // If the request comes from Turbo, only send the HTML to update using a TurboStreamResponse - return $this->render('task/success.stream.html.twig', ['task' => $task], new TurboStreamResponse()); + if (TurboBundle::STREAM_FORMAT === $request->getPreferredFormat()) { + // If the request comes from Turbo, set the content type as text/vnd.turbo-stream.html and only send the HTML to update + $request->setFormat(TurboBundle::STREAM_FORMAT); + return $this->render('task/success.stream.html.twig', ['task' => $task]); } // If the client doesn't support JavaScript, or isn't using Turbo, the form still works as usual. diff --git a/src/Turbo/Resources/config/services.php b/src/Turbo/Resources/config/services.php index cb2edf4321b..0cd1e6a1d5f 100644 --- a/src/Turbo/Resources/config/services.php +++ b/src/Turbo/Resources/config/services.php @@ -16,7 +16,6 @@ use Symfony\UX\Turbo\Broadcaster\ImuxBroadcaster; use Symfony\UX\Turbo\Broadcaster\TwigBroadcaster; use Symfony\UX\Turbo\Doctrine\BroadcastListener; -use Symfony\UX\Turbo\Stream\AddTurboStreamFormatSubscriber; use Symfony\UX\Turbo\Twig\TwigExtension; /* @@ -25,9 +24,6 @@ return static function (ContainerConfigurator $container): void { $container->services() - ->set('turbo.kernel.event_subscriber', AddTurboStreamFormatSubscriber::class) - ->tag('kernel.event_subscriber') - ->set('turbo.broadcaster.imux', ImuxBroadcaster::class) ->args([tagged_iterator('turbo.broadcaster')]) diff --git a/src/Turbo/Stream/AddTurboStreamFormatSubscriber.php b/src/Turbo/Stream/AddTurboStreamFormatSubscriber.php deleted file mode 100644 index 0d5bb0e9225..00000000000 --- a/src/Turbo/Stream/AddTurboStreamFormatSubscriber.php +++ /dev/null @@ -1,67 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\UX\Turbo\Stream; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpKernel\Event\RequestEvent; -use Symfony\Component\HttpKernel\Event\ResponseEvent; -use Symfony\Component\HttpKernel\KernelEvents; - -/** - * Detects if it's a Turbo Stream request and sets the format accordingly. - * - * @author Kévin Dunglas - * - * @experimental - */ -final class AddTurboStreamFormatSubscriber implements EventSubscriberInterface -{ - public function onKernelRequest(RequestEvent $event): void - { - $request = $event->getRequest(); - if (!($accept = $request->headers->get('Accept')) || 0 !== strpos($accept, TurboStreamResponse::STREAM_MEDIA_TYPE)) { - return; - } - - $request->setFormat(TurboStreamResponse::STREAM_FORMAT, TurboStreamResponse::STREAM_MEDIA_TYPE); - $request->setRequestFormat(TurboStreamResponse::STREAM_FORMAT); - } - - /** - * Prevents issues with Turbo Frames when sending a response that isn't in the Turbo Stream format. - */ - public function onKernelResponse(ResponseEvent $event): void - { - $response = $event->getResponse(); - if ($response instanceof TurboStreamResponse) { - return; - } - - $request = $event->getRequest(); - if (TurboStreamResponse::STREAM_FORMAT === $request->getRequestFormat(null)) { - $request->setRequestFormat(null); - } - } - - /** - * Executed before AddRequestFormatsListener and ResponseListener. - * - * @return array - */ - public static function getSubscribedEvents(): array - { - return [ - KernelEvents::REQUEST => ['onKernelRequest', 110], - KernelEvents::RESPONSE => ['onKernelResponse', 10], - ]; - } -} diff --git a/src/Turbo/Stream/TurboStreamResponse.php b/src/Turbo/Stream/TurboStreamResponse.php deleted file mode 100644 index 962dab4be60..00000000000 --- a/src/Turbo/Stream/TurboStreamResponse.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\UX\Turbo\Stream; - -use Symfony\Component\HttpFoundation\Response; - -/** - * A response in the Turbo Stream format. - * - * @author Kévin Dunglas - * - * @experimental - */ -final class TurboStreamResponse extends Response -{ - public const STREAM_FORMAT = 'turbo_stream'; - public const STREAM_MEDIA_TYPE = 'text/vnd.turbo-stream.html'; -} diff --git a/src/Turbo/Tests/app/Kernel.php b/src/Turbo/Tests/app/Kernel.php index f6910471f6e..782d1ba0b63 100644 --- a/src/Turbo/Tests/app/Kernel.php +++ b/src/Turbo/Tests/app/Kernel.php @@ -34,7 +34,6 @@ use Symfony\Component\Mercure\HubInterface; use Symfony\Component\Mercure\Update; use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator; -use Symfony\UX\Turbo\Stream\TurboStreamResponse; use Symfony\UX\Turbo\TurboBundle; use Symfony\WebpackEncoreBundle\WebpackEncoreBundle; use Twig\Environment; @@ -131,11 +130,14 @@ public function getProjectDir(): string public function form(Request $request, Environment $twig): Response { - if (TurboStreamResponse::STREAM_FORMAT === $request->getPreferredFormat()) { - return new TurboStreamResponse($twig->render('form.stream.html.twig')); + if (TurboBundle::STREAM_FORMAT === $request->getPreferredFormat()) { + $request->setRequestFormat(TurboBundle::STREAM_FORMAT); + $response = (new Response($twig->render('form.stream.html.twig'))); + } else { + $response = new Response('Turbo not installed, default to plain HTML.'); } - return new Response('Turbo not installed, default to plain HTML.'); + return $response->setVary('Accept'); } public function chat(Request $request, FormFactoryInterface $formFactory, HubInterface $mercureHub, Environment $twig): Response diff --git a/src/Turbo/TurboBundle.php b/src/Turbo/TurboBundle.php index 134c15de545..0a0e801c995 100644 --- a/src/Turbo/TurboBundle.php +++ b/src/Turbo/TurboBundle.php @@ -14,6 +14,7 @@ use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\PassConfig; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Bundle\Bundle; /** @@ -23,6 +24,14 @@ */ final class TurboBundle extends Bundle { + public const STREAM_FORMAT = 'turbo_stream'; + public const STREAM_MEDIA_TYPE = 'text/vnd.turbo-stream.html'; + + public function boot(): void + { + (new Request())->setFormat(self::STREAM_FORMAT, self::STREAM_MEDIA_TYPE); + } + public function build(ContainerBuilder $container): void { parent::build($container);