diff --git a/src/TurboStreamRender/src/Core/TurboStream.php b/src/TurboStreamRender/src/Core/TurboStream.php new file mode 100644 index 00000000000..77616975e9b --- /dev/null +++ b/src/TurboStreamRender/src/Core/TurboStream.php @@ -0,0 +1,19 @@ +addStream(new TurboStream($target, $action, $view, $parameters)); + } + + public function addStream(TurboStream $stream): self + { + $this->streams[] = $stream; + + return $this; + } + + /** + * @return TurboStream[] + */ + public function all(): array + { + return $this->streams; + } +} diff --git a/src/TurboStreamRender/src/Core/TurboStreamRenderer.php b/src/TurboStreamRender/src/Core/TurboStreamRenderer.php new file mode 100644 index 00000000000..b6d4e973ad3 --- /dev/null +++ b/src/TurboStreamRender/src/Core/TurboStreamRenderer.php @@ -0,0 +1,68 @@ +renderer = $renderer; + } + + /** + * @throws \InvalidRendererException + */ + public function renderView(string $view, array $parameters = []): string + { + try { + $renderer = $this->renderer; + return $renderer($view, $parameters); + }catch (\Throwable $e) { + throw new \InvalidRendererException($e->getMessage(), $e->getCode(), $e); + } + } + + public function renderAsStreamView(string $target, TurboAction $action, string $view, array $parameters = []): string + { + $streams = (new TurboStreamCollection())->add($target, $action, $view, $parameters); + + return $this->renderTurboStreamsView($streams->all()); + } + + /** + * @throws \InvalidRendererException + */ + public function renderTurboStreamsView(array $streams): string + { + $response = ""; + foreach ($streams as $stream) { + $content = $this->renderView($stream['view'], $stream['parameters']); + $response .= $this->wrapWithTurboStream($stream['target'], $stream['action'], $content); + $response .= "\n"; + } + + return $response; + } + + private function wrapWithTurboStream(string $target, TurboAction $action, string $content): string + { + return << + + + HTML; + } +} diff --git a/src/TurboStreamRender/src/Enum/TurboAction.php b/src/TurboStreamRender/src/Enum/TurboAction.php new file mode 100644 index 00000000000..19081557392 --- /dev/null +++ b/src/TurboStreamRender/src/Enum/TurboAction.php @@ -0,0 +1,17 @@ +add($target, $action, $view, $parameters); + + return $this->renderTurboStreamsView($streams->all()); + } + + /** + * @param TurboStream[] $streams + */ + protected function renderTurboStreamsView(array $streams): string + { + return $this->getTurboStreamRenderer()->renderTurboStreamsView($streams); + } + + private function wrapWithTurboStream(string $target, TurboAction $action, string $content): string + { + return << + + + HTML; + } +} diff --git a/src/TurboStreamResponse/src/Trait/TurboResponseTrait.php b/src/TurboStreamResponse/src/Trait/TurboResponseTrait.php new file mode 100644 index 00000000000..249f153242a --- /dev/null +++ b/src/TurboStreamResponse/src/Trait/TurboResponseTrait.php @@ -0,0 +1,66 @@ +renderTurboStreams([new TurboStream($target, $action, $view, $parameters)]); + } + + /** + * @param TurboStream[] $streams + */ + protected function renderTurboStreams(array $streams): Response + { + $content = $this->renderTurboStreamsView($streams); + $response ??= new Response(); + + // I would like to keep this part of the standard AbstractController, but I don't really like the idea of duplication the code. + // Any suggestions for a way to reuse it? + + foreach ($streams as $stream) { + if (200 === $response->getStatusCode()) { + $parameters = $stream->getParameters(); + foreach ($parameters as $v) { + if ($v instanceof FormInterface && $v->isSubmitted() && !$v->isValid()) { + $response->setStatusCode(422); + break 2; + } + } + } + } + + $response->setContent($content); + $response->headers->set('Content-Type', TurboBundle::STREAM_MEDIA_TYPE); + + return $response; + } + + private function wrapWithTurboStream(string $target, TurboAction $action, string $content): string + { + return << + + + HTML; + } +} diff --git a/ux.symfony.com/templates/components/TurboStream.html.twig b/ux.symfony.com/templates/components/TurboStream.html.twig new file mode 100644 index 00000000000..4a083d8d18f --- /dev/null +++ b/ux.symfony.com/templates/components/TurboStream.html.twig @@ -0,0 +1,5 @@ + + +