diff --git a/.github/workflows/test-turbo.yml b/.github/workflows/test-turbo.yml index fb2b145e4c3..47008d2605a 100644 --- a/.github/workflows/test-turbo.yml +++ b/.github/workflows/test-turbo.yml @@ -8,6 +8,9 @@ on: paths: - 'src/Turbo/**' +env: + SYMFONY_REQUIRE: '>=5.4' + jobs: phpstan: runs-on: ubuntu-latest @@ -38,11 +41,11 @@ jobs: strategy: fail-fast: false matrix: - php-version: ['8.1', '8.3'] + php-version: ['8.1', '8.4'] include: - php-version: '8.1' dependency-version: 'lowest' - - php-version: '8.3' + - php-version: '8.4' dependency-version: 'highest' services: @@ -69,6 +72,9 @@ jobs: with: php-version: ${{ matrix.php-version }} + - name: Install symfony/flex + run: composer global config allow-plugins.symfony/flex true && composer global require symfony/flex + - name: Install Turbo packages uses: ramsey/composer-install@v3 with: @@ -101,6 +107,8 @@ jobs: - name: Run tests working-directory: src/Turbo - run: vendor/bin/simple-phpunit + run: | + [ 'lowest' = '${{ matrix.dependency-version }}' ] && export SYMFONY_DEPRECATIONS_HELPER=weak + vendor/bin/simple-phpunit env: SYMFONY_DEPRECATIONS_HELPER: 'max[self]=1' diff --git a/src/Turbo/CHANGELOG.md b/src/Turbo/CHANGELOG.md index d3e4d1c9eeb..df89967eb89 100644 --- a/src/Turbo/CHANGELOG.md +++ b/src/Turbo/CHANGELOG.md @@ -4,6 +4,7 @@ - Add `Helper/TurboStream::append()` et al. methods - Add `TurboStreamResponse` +- Add `<twig:Turbo:Stream:*>` components ## 2.19.0 diff --git a/src/Turbo/composer.json b/src/Turbo/composer.json index 46acc1f579c..e3cb46514a4 100644 --- a/src/Turbo/composer.json +++ b/src/Turbo/composer.json @@ -52,6 +52,7 @@ "symfony/property-access": "^5.4|^6.0|^7.0", "symfony/security-core": "^5.4|^6.0|^7.0", "symfony/stopwatch": "^5.4|^6.0|^7.0", + "symfony/ux-twig-component": "^2.21", "symfony/twig-bundle": "^5.4|^6.0|^7.0", "symfony/web-profiler-bundle": "^5.4|^6.0|^7.0", "symfony/webpack-encore-bundle": "^2.1.1", diff --git a/src/Turbo/templates/components/Stream/After.html.twig b/src/Turbo/templates/components/Stream/After.html.twig new file mode 100644 index 00000000000..3105a376dec --- /dev/null +++ b/src/Turbo/templates/components/Stream/After.html.twig @@ -0,0 +1,5 @@ +{% props target -%} + +<turbo-stream action="after" targets="{{ target }}" {{ attributes }}> + <template>{% block content %}{% endblock %}</template> +</turbo-stream> diff --git a/src/Turbo/templates/components/Stream/Append.html.twig b/src/Turbo/templates/components/Stream/Append.html.twig new file mode 100644 index 00000000000..aea22f28227 --- /dev/null +++ b/src/Turbo/templates/components/Stream/Append.html.twig @@ -0,0 +1,5 @@ +{% props target -%} + +<turbo-stream action="append" targets="{{ target }}" {{ attributes }}> + <template>{% block content %}{% endblock %}</template> +</turbo-stream> diff --git a/src/Turbo/templates/components/Stream/Before.html.twig b/src/Turbo/templates/components/Stream/Before.html.twig new file mode 100644 index 00000000000..3ffdeded6aa --- /dev/null +++ b/src/Turbo/templates/components/Stream/Before.html.twig @@ -0,0 +1,5 @@ +{% props target -%} + +<turbo-stream action="before" targets="{{ target }}" {{ attributes }}> + <template>{% block content %}{% endblock %}</template> +</turbo-stream> diff --git a/src/Turbo/templates/components/Stream/Prepend.html.twig b/src/Turbo/templates/components/Stream/Prepend.html.twig new file mode 100644 index 00000000000..b75d3534ef9 --- /dev/null +++ b/src/Turbo/templates/components/Stream/Prepend.html.twig @@ -0,0 +1,5 @@ +{% props target -%} + +<turbo-stream action="prepend" targets="{{ target }}" {{ attributes }}> + <template>{% block content %}{% endblock %}</template> +</turbo-stream> diff --git a/src/Turbo/templates/components/Stream/Refresh.html.twig b/src/Turbo/templates/components/Stream/Refresh.html.twig new file mode 100644 index 00000000000..182129e6533 --- /dev/null +++ b/src/Turbo/templates/components/Stream/Refresh.html.twig @@ -0,0 +1,3 @@ +{% props requestId = null -%} + +<turbo-stream action="refresh"{% if requestId is not null %} request-id="{{ requestId }}"{% endif %} {{ attributes }}></turbo-stream> diff --git a/src/Turbo/templates/components/Stream/Remove.html.twig b/src/Turbo/templates/components/Stream/Remove.html.twig new file mode 100644 index 00000000000..9e3c023480d --- /dev/null +++ b/src/Turbo/templates/components/Stream/Remove.html.twig @@ -0,0 +1,3 @@ +{% props target -%} + +<turbo-stream action="remove" targets="{{ target }}" {{ attributes }}></turbo-stream> diff --git a/src/Turbo/templates/components/Stream/Replace.html.twig b/src/Turbo/templates/components/Stream/Replace.html.twig new file mode 100644 index 00000000000..d11598f6885 --- /dev/null +++ b/src/Turbo/templates/components/Stream/Replace.html.twig @@ -0,0 +1,5 @@ +{% props target, morph = false -%} + +<turbo-stream action="replace" targets="{{ target }}"{% if morph %} method="morph"{% endif %} {{ attributes }}> + <template>{% block content %}{% endblock %}</template> +</turbo-stream> diff --git a/src/Turbo/templates/components/Stream/Update.html.twig b/src/Turbo/templates/components/Stream/Update.html.twig new file mode 100644 index 00000000000..f15fbfc0094 --- /dev/null +++ b/src/Turbo/templates/components/Stream/Update.html.twig @@ -0,0 +1,5 @@ +{% props target, morph = false -%} + +<turbo-stream action="update" targets="{{ target }}"{% if morph %} method="morph"{% endif %} {{ attributes }}> + <template>{% block content %}{% endblock %}</template> +</turbo-stream> diff --git a/src/Turbo/tests/app/Kernel.php b/src/Turbo/tests/app/Kernel.php index f61de905272..5e2594135e0 100644 --- a/src/Turbo/tests/app/Kernel.php +++ b/src/Turbo/tests/app/Kernel.php @@ -38,6 +38,7 @@ use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator; use Symfony\UX\StimulusBundle\StimulusBundle; use Symfony\UX\Turbo\TurboBundle; +use Symfony\UX\TwigComponent\TwigComponentBundle; use Symfony\WebpackEncoreBundle\WebpackEncoreBundle; use Twig\Environment; @@ -54,6 +55,7 @@ public function registerBundles(): iterable yield new DoctrineBundle(); yield new TwigBundle(); yield new MercureBundle(); + yield new TwigComponentBundle(); yield new TurboBundle(); yield new WebpackEncoreBundle(); yield new StimulusBundle(); @@ -120,6 +122,11 @@ protected function configureContainer(ContainerConfigurator $container): void ], ], ]); + + $container->extension('twig_component', [ + 'anonymous_template_directory' => 'components/', + 'defaults' => ['App\Twig\Components\\' => 'components/'], + ]); } protected function configureRoutes(RoutingConfigurator $routes): void diff --git a/src/Turbo/tests/app/templates/broadcast/Artist.stream.html.twig b/src/Turbo/tests/app/templates/broadcast/Artist.stream.html.twig index 7d7d7bd59f4..f975b3ca5ca 100644 --- a/src/Turbo/tests/app/templates/broadcast/Artist.stream.html.twig +++ b/src/Turbo/tests/app/templates/broadcast/Artist.stream.html.twig @@ -1,19 +1,15 @@ {% block create %} - <turbo-stream action="append" target="artists"> - <template> - <div id="{{ 'artist_' ~ id }}"><a href="{{ path('artist', {id: id}) }}">{{ entity.name }} (#{{ id }})</a></div> - </template> - </turbo-stream> + <twig:Turbo:Stream:Append target="#artists"> + <div id="artist_{{ id }}"><a href="{{ path('artist', {id: id}) }}">{{ entity.name }} (#{{ id }})</a></div> + </twig:Turbo:Stream:Append> {% endblock %} {% block update %} - <turbo-stream action="update" target="artist_{{ id }}"> - <template> - {{ entity.name }} (#{{ id }}, updated) - </template> - </turbo-stream> + <twig:Turbo:Stream:Update target="#artist_{{ id }}"> + {{ entity.name }} (#{{ id }}, updated) + </twig:Turbo:Stream:Update> {% endblock %} {% block remove %} - <turbo-stream action="remove" target="artist_{{ id }}"></turbo-stream> + <twig:Turbo:Stream:Remove target="#artist_{{ id }}"></twig:Turbo:Stream:Remove> {% endblock %} diff --git a/src/Turbo/tests/app/templates/broadcast/Book.stream.html.twig b/src/Turbo/tests/app/templates/broadcast/Book.stream.html.twig index 94b1d72afc2..1ed70a70de1 100644 --- a/src/Turbo/tests/app/templates/broadcast/Book.stream.html.twig +++ b/src/Turbo/tests/app/templates/broadcast/Book.stream.html.twig @@ -1,19 +1,15 @@ {% block create %} - <turbo-stream action="append" target="books"> - <template> - <div id="{{ 'book_' ~ id }}">{{ entity.title }} (#{{ id }})</div> - </template> - </turbo-stream> + <twig:Turbo:Stream:Append target="#books"> + <div id="book_{{ id }}">{{ entity.title }} (#{{ id }})</div> + </twig:Turbo:Stream:Append> {% endblock %} {% block update %} - <turbo-stream action="update" target="book_{{ id }}"> - <template> - {{ entity.title }} (#{{ id }}, updated) - </template> - </turbo-stream> + <twig:Turbo:Stream:Update target="#book_{{ id }}"> + {{ entity.title }} (#{{ id }}, updated) + </twig:Turbo:Stream:Update> {% endblock %} {% block remove %} - <turbo-stream action="remove" target="book_{{ id }}"></turbo-stream> + <twig:Turbo:Stream:Remove target="#book_{{ id }}"></twig:Turbo:Stream:Remove> {% endblock %} diff --git a/src/Turbo/tests/app/templates/broadcast/Song.stream.html.twig b/src/Turbo/tests/app/templates/broadcast/Song.stream.html.twig index 14b283c435c..f2719f3b1e8 100644 --- a/src/Turbo/tests/app/templates/broadcast/Song.stream.html.twig +++ b/src/Turbo/tests/app/templates/broadcast/Song.stream.html.twig @@ -1,19 +1,15 @@ {% block create %} - <turbo-stream action="append" target="songs"> - <template> - <div id="{{ 'song_' ~ id }}">{{ entity.title }} (#{{ id }}){% if entity.artist %} by {{ entity.artist.name }} (#{{ entity.artist.id }}){% endif %}</div> - </template> - </turbo-stream> + <twig:Turbo:Stream:Append target="#songs"> + <div id="song_{{ id }}">{{ entity.title }} (#{{ id }}){% if entity.artist %} by {{ entity.artist.name }} (#{{ entity.artist.id }}){% endif %}</div> + </twig:Turbo:Stream:Append> {% endblock %} {% block update %} - <turbo-stream action="update" target="song_{{ id }}"> - <template> - {{ entity.title }} (#{{ id }}, updated) - </template> - </turbo-stream> + <twig:Turbo:Stream:Update target="#song_{{ id }}"> + {{ entity.title }} (#{{ id }}, updated) + </twig:Turbo:Stream:Update> {% endblock %} {% block remove %} - <turbo-stream action="remove" target="song_{{ id }}"></turbo-stream> + <twig:Turbo:Stream:Remove target="#song_{{ id }}"></twig:Turbo:Stream:Remove> {% endblock %} diff --git a/src/Turbo/tests/app/templates/chat/message.stream.html.twig b/src/Turbo/tests/app/templates/chat/message.stream.html.twig index 00bffdd5f23..791a5dcce01 100644 --- a/src/Turbo/tests/app/templates/chat/message.stream.html.twig +++ b/src/Turbo/tests/app/templates/chat/message.stream.html.twig @@ -1,5 +1,3 @@ -<turbo-stream action="append" target="messages"> - <template> - <div>{{ message }}</div> - </template> -</turbo-stream> +<twig:Turbo:Stream:Append target="#messages"> + <div>{{ message }}</div> +</twig:Turbo:Stream:Append> diff --git a/src/Turbo/tests/app/templates/form.stream.html.twig b/src/Turbo/tests/app/templates/form.stream.html.twig index 043c31da36a..0c848d830f1 100644 --- a/src/Turbo/tests/app/templates/form.stream.html.twig +++ b/src/Turbo/tests/app/templates/form.stream.html.twig @@ -1,13 +1,9 @@ -<turbo-stream action="replace" target="form"> - <template> - <div id="form"> - This div replaces the existing element with the DOM ID "form". - </div> - </template> -</turbo-stream> +<twig:Turbo:Stream:Replace target="#form"> + <div id="form"> + This div replaces the existing element with the DOM ID "form". + </div> +</twig:Turbo:Stream:Replace> -<turbo-stream action="append" target="another_block"> - <template> - <div>Appended!</div> - </template> -</turbo-stream> +<twig:Turbo:Stream:Append target="#another_block"> + <div>Appended!</div> +</twig:Turbo:Stream:Append>