Repository: symfony/ux (php)

Issue:
Turbo & Mercure documentation does not work
The Turbo / Mercure documentation is inconsistent: 

The following (can be found https://github.com/symfony/ux/blob/2.x/src/Turbo/doc/index.rst?plain=1#L519-L522) does generate an error:
```yaml
# config/packages/turbo.yaml
turbo:
    mercure:
        hubs: [default]
```

> Unrecognized option "mercure" under "turbo". Available options are "broadcast", "default_transport".

I don't get how this can work, as there is no code referring to this option in the configuration: https://github.com/symfony/ux/blob/2.x/src/Turbo/src/DependencyInjection/Configuration.php

Pull request description:
[Turbo] Remove obselete Mercure configuration (docs)
| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | yes/no <!-- please update src/**/CHANGELOG.md files -->
| Issues        | Fix #2518
| License       | MIT


This PR replaces #2519 (that did not use current config format) and add the changes missing on the same page.

- [Update Mercure bundle documentation](https://github.com/symfony/ux/commit/ef688d4b9f838c456316824b187155c5fc651ff2)
- [Fix Mercure controller configuration](https://github.com/symfony/ux/commit/f221d4dac6ecdb211af2557b184156171c08c864)
- [Remove obselete Mercure turbo/hub configuration](https://github.com/symfony/ux/commit/a8403c011d6d662a11e409709c8abe3076bbbcc3)
- [Remove very old versionadded warning](https://github.com/symfony/ux/commit/c8dcb5efb3b5da0230404d75589f0fa2b7592586)
- [Remove Symfony 6.2+ comment](https://github.com/symfony/ux/commit/3a88f32089e2691ee0f6a315318671822e3e50fe)



Patch:
diff --git a/src/LiveComponent/src/ComponentWithFormTrait.php b/src/LiveComponent/src/ComponentWithFormTrait.php
index 8f2aceab..c8ab525d 100644
--- a/src/LiveComponent/src/ComponentWithFormTrait.php
+++ b/src/LiveComponent/src/ComponentWithFormTrait.php
@@ -11,7 +11,6 @@
 
 namespace Symfony\UX\LiveComponent;
 
-use Symfony\Component\Form\ChoiceList\View\ChoiceGroupView;
 use Symfony\Component\Form\ClearableErrorsInterface;
 use Symfony\Component\Form\FormInterface;
 use Symfony\Component\Form\FormView;
@@ -256,39 +255,25 @@ trait ComponentWithFormTrait
                 continue;
             }
 
-            // <input type="checkbox">
             if (\array_key_exists('checked', $child->vars)) {
+                // special handling for check boxes
                 $values[$name] = $child->vars['checked'] ? $child->vars['value'] : null;
                 continue;
             }
 
-            // <select> - Simulate browser behavior
-            // When no option is selected, browsers send the value of the first
-            // option, when the following conditions are met:
-            if (
-                \array_key_exists('choices', $child->vars)
-                && $child->vars['choices']                  // has defined choices
-                && $child->vars['required']                 // is required
-                && !$child->vars['disabled']                // is not disabled
-                && '' === $child->vars['value']             // has no value set  ("0" can be a value)
-                && !array_diff_key(
-                    /* @see \Symfony\Component\Form\Extension\Core\Type\ChoiceType::buildView() */
-                    array_flip(['choices', 'expanded', 'multiple', 'placeholder', 'placeholder_in_choices', 'preferred_choices']),
-                    $child->vars,
-                )
-                && !$child->vars['expanded']                // is a <select>     (not a radio/checkbox)
-                && !$child->vars['multiple']                // is not multiple
-                && !\is_string($child->vars['placeholder'])  // has no placeholder (empty string is valid)
+            if (\array_key_exists('choices', $child->vars)
+                && $child->vars['required']
+                && !$child->vars['disabled']
+                && !$child->vars['value']
+                && (false === $child->vars['placeholder'] || null === $child->vars['placeholder'])
+                && !$child->vars['multiple']
+                && !$child->vars['expanded']
+                && $child->vars['choices']
             ) {
-                $choices = $child->vars['choices'];
-                do {
-                    $choice = $choices[array_key_first($choices)];
-                    if (!$choice instanceof ChoiceGroupView) {
-                        break;
-                    }
-                } while ($choices = $choice->choices);
-
-                $values[$name] = $choice?->value;
+                if (null !== $firstKey = array_key_first($child->vars['choices'])) {
+                    $values[$name] = $child->vars['choices'][$firstKey]->value ?? null;
+                }
+
                 continue;
             }
 
diff --git a/src/Turbo/doc/index.rst b/src/Turbo/doc/index.rst
index 4618bd70..83b781de 100644
--- a/src/Turbo/doc/index.rst
+++ b/src/Turbo/doc/index.rst
@@ -342,11 +342,6 @@ clients. There are two main ways to receive the updates:
 Forms
 ^^^^^
 
-.. versionadded:: 2.1
-
-    Prior to 2.1, ``TurboStreamResponse::STREAM_FORMAT`` was used instead of ``TurboBundle::STREAM_FORMAT``.
-    Also, one had to return a new ``TurboStreamResponse()`` object as the third argument to ``$this->render()``.
-
 Let's discover how to use Turbo Streams to enhance your `Symfony forms`_::
 
     // src/Controller/TaskController.php
@@ -383,7 +378,6 @@ Let's discover how to use Turbo Streams to enhance your `Symfony forms`_::
                 return $this->redirectToRoute('task_success', [], Response::HTTP_SEE_OTHER);
             }
 
-            // Symfony 6.2+
             return $this->render('task/new.html.twig', [
                 'form' => $form,
             ]);
@@ -500,7 +494,7 @@ Then, enable the "mercure stream" controller in ``assets/controllers.json``:
         "mercure-turbo-stream": {
     +         "enabled": true,
     -         "enabled": false,
-            "fetch": "lazy"
+            "fetch": "eager"
         }
     },
 
@@ -512,14 +506,19 @@ If you use Symfony Flex, the configuration has been generated for you,
 be sure to update the ``MERCURE_URL`` in the ``.env`` file to point to a
 Mercure Hub (it's not necessary if you are using Symfony Docker).
 
-Otherwise, configure Mercure Hub(s) to use:
+Otherwise, configure Mercure Hub(s) as explained in the documentation:
 
 .. code-block:: yaml
 
-    # config/packages/turbo.yaml
-    turbo:
-        mercure:
-            hubs: [default]
+    # config/packages/mercure.yaml
+    mercure:
+        hubs:
+            default:
+                url: '%env(MERCURE_URL)%'
+                public_url: '%env(MERCURE_PUBLIC_URL)%'
+                jwt:
+                    secret: '%env(MERCURE_JWT_SECRET)%'
+                    publish: '*'
 
 Let's create our chat::
 
@@ -785,13 +784,6 @@ the following configuration:
                 url: https://hub2.example.net/.well-known/mercure
                 jwt: snip
 
-.. code-block:: yaml
-
-    # config/packages/turbo.yaml
-    turbo:
-        mercure:
-            hubs: [hub1, hub2]
-
 Use the appropriate Mercure ``HubInterface`` service to send a change
 using a specific transport::
 


Test patch:
diff --git a/src/LiveComponent/tests/Fixtures/Form/FormWithManyDifferentFieldsType.php b/src/LiveComponent/tests/Fixtures/Form/FormWithManyDifferentFieldsType.php
index 59537991..f2a0e322 100644
--- a/src/LiveComponent/tests/Fixtures/Form/FormWithManyDifferentFieldsType.php
+++ b/src/LiveComponent/tests/Fixtures/Form/FormWithManyDifferentFieldsType.php
@@ -65,15 +65,6 @@ class FormWithManyDifferentFieldsType extends AbstractType
                     'foo' => 1,
                 ],
             ])
-            ->add('choice_required_without_placeholder_and_choice_group', ChoiceType::class, [
-                'choices' => [
-                    'Bar Group' => [
-                        'Bar Label' => 'ok',
-                        'Foo Label' => 'foo_value',
-                    ],
-                    'foo' => 1,
-                ],
-            ])
             ->add('choice_expanded', ChoiceType::class, [
                 'choices' => [
                     'foo' => 1,
diff --git a/src/LiveComponent/tests/Functional/Form/ComponentWithFormTest.php b/src/LiveComponent/tests/Functional/Form/ComponentWithFormTest.php
index bfbe477c..a3ed0f7c 100644
--- a/src/LiveComponent/tests/Functional/Form/ComponentWithFormTest.php
+++ b/src/LiveComponent/tests/Functional/Form/ComponentWithFormTest.php
@@ -181,7 +181,6 @@ class ComponentWithFormTest extends KernelTestCase
             'choice_required_with_placeholder' => '',
             'choice_required_with_empty_placeholder' => '',
             'choice_required_without_placeholder' => '2',
-            'choice_required_without_placeholder_and_choice_group' => 'ok',
             'choice_expanded' => '',
             'choice_multiple' => ['2'],
             'select_multiple' => ['2'],
diff --git a/src/LiveComponent/tests/Unit/Form/ComponentWithFormTest.php b/src/LiveComponent/tests/Unit/Form/ComponentWithFormTest.php
index a7062605..931430d8 100644
--- a/src/LiveComponent/tests/Unit/Form/ComponentWithFormTest.php
+++ b/src/LiveComponent/tests/Unit/Form/ComponentWithFormTest.php
@@ -46,7 +46,6 @@ class ComponentWithFormTest extends KernelTestCase
                 'choice_required_with_placeholder' => '',
                 'choice_required_with_empty_placeholder' => '',
                 'choice_required_without_placeholder' => '2',
-                'choice_required_without_placeholder_and_choice_group' => 'ok',
                 'choice_expanded' => '',
                 'choice_multiple' => ['2'],
                 'select_multiple' => ['2'],