Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[2.7][Form] Fixed ChoiceType with legacy ChoiceList #14551

Merged
merged 1 commit into from May 20, 2015

Conversation

xelaris
Copy link
Contributor

@xelaris xelaris commented May 5, 2015

Q A
Bug fix? yes
New feature? no
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #14382
License MIT
Doc PR

The "Backwards compatibility" condition doesn't grap (e.g. when passing a SimpleChoiceList as choice_list on ChoiceType), as the default value for the ChoiceType option preferred_choices is array() instead of null. So I changed the condition from null === $preferredChoices to empty($preferredChoices).
Then there was an issue with accessing attr in form_div_layout.html.twig, since the deprecated Symfony\Component\Form\Extension\Core\View\ChoiceView doesn't provide an attr attribute. Since the docblocks of Symfony\Component\Form\ChoiceList\View\ChoiceListView state $choices and $preferredChoices to be instances of Symfony\Component\Form\ChoiceList\View\ChoiceView instead of Symfony\Component\Form\Extension\Core\View\ChoiceView I fixed the template issue by mapping the deprecated ChoiceView objects to the new one with an empty attr.

@webmozart Could you have a look at it, please?

Without this PR the following example would render numeric values as labels:

        $formBuilder->add('choices', 'choice', array(
            'choice_list' => new SimpleChoiceList(array(
                'creditcard' => 'Credit card payment',
                'cash' => 'Cash payment'
            ))
        ));

@webmozart
Copy link
Contributor

Great PR!

&& null === $label && null === $index && null === $groupBy && null === $attr) {
return new ChoiceListView($list->getRemainingViews(), $list->getPreferredViews());
$mapToNonLegacyChoiceView = function (LegacyChoiceView $choiceView) {
return new ChoiceView($choiceView->label, $choiceView->value, $choiceView->data);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a more efficient solution would be to simply define the "attr" property dynamically:

$choiceView->attr = array();

After all, this method is called pretty often.

@webmozart
Copy link
Contributor

Apart from my comment, I don't have any objections :) 👍

@xelaris
Copy link
Contributor Author

xelaris commented May 5, 2015

Keeping the legacy ChoiceView objects (and adding the attr attribute dynamically) to introduce as less overhead as possible sounds good, but changing it causes testLegacySubmitSingleExpandedObjectChoices tests to fail, since ChoiceType::addSubForm() expects $coiceView to be instance of the new ChoiceView. As addSubForm is a private method I think it is save to typehint with the deprecated ChoiceView and accessing the attr only if it is an instance of the new one, isn't it?
Apart from the efficiency, I think it would be more clean and safe to provide ChoiceListViews with instances of the new ChoiceView only (as stated in ChoiceListView php doc) . But I don't know what matters more here.

@webmozart If you are in favor of changing the typehint to enable the usage of the legacy ChoiceViews and save the mapping, I would to this change:

@@ -408,12 +409,12 @@ class ChoiceType extends AbstractType
      *
      * @return mixed
      */
-    private function addSubForm(FormBuilderInterface $builder, $name, ChoiceView $choiceView, array $options)
+    private function addSubForm(FormBuilderInterface $builder, $name, LegacyChoiceView $choiceView, array $options)
     {
         $choiceOpts = array(
             'value' => $choiceView->value,
             'label' => $choiceView->label,
-            'attr' => $choiceView->attr,
+            'attr' => $choiceView instanceof ChoiceView ? $choiceView->attr : array(),
             'translation_domain' => $options['translation_domain'],
             'block_name' => 'entry',
         );

@jakzal jakzal added the Form label May 12, 2015
@soullivaneuh
Copy link
Contributor

👍

Will this PR fix #14382 without any code change on bundles / core project?

Thanks.

@xelaris
Copy link
Contributor Author

xelaris commented May 18, 2015

@soullivaneuh Yes, this fixes the code which keeps BC.

@fabpot
Copy link
Member

fabpot commented May 20, 2015

Thank you @xelaris.

@fabpot fabpot merged commit a98e484 into symfony:2.7 May 20, 2015
fabpot added a commit that referenced this pull request May 20, 2015
This PR was merged into the 2.7 branch.

Discussion
----------

[2.7][Form] Fixed ChoiceType with legacy ChoiceList

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #14382
| License       | MIT
| Doc PR        |

The "Backwards compatibility" condition doesn't grap (e.g. when passing a `SimpleChoiceList` as `choice_list` on `ChoiceType`), as the default value for the `ChoiceType` option `preferred_choices` is `array()` instead of `null`. So I changed the condition from `null === $preferredChoices` to `empty($preferredChoices)`.
Then there was an issue with accessing `attr` in `form_div_layout.html.twig`, since the deprecated `Symfony\Component\Form\Extension\Core\View\ChoiceView` doesn't provide an `attr` attribute. Since the docblocks of `Symfony\Component\Form\ChoiceList\View\ChoiceListView` state `$choices` and `$preferredChoices` to be instances of `Symfony\Component\Form\ChoiceList\View\ChoiceView` instead of `Symfony\Component\Form\Extension\Core\View\ChoiceView` I fixed the template issue by mapping the deprecated `ChoiceView` objects to the new one with an empty `attr`.

@webmozart Could you have a look at it, please?

Without this PR the following example would render numeric values as labels:
```php
        $formBuilder->add('choices', 'choice', array(
            'choice_list' => new SimpleChoiceList(array(
                'creditcard' => 'Credit card payment',
                'cash' => 'Cash payment'
            ))
        ));
```

Commits
-------

a98e484 [Form] Fix ChoiceType with legacy ChoiceList
@trsteel88
Copy link
Contributor

This is still causing issues when I use an ObjectChoiceList and it is grouped by something.

e.g:

$resolver->setDefaults(array(
    'choice_list' =>  new ObjectChoiceList($someEntities, 'name', array(), 'some_group', 'id');
));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants