sonata-project / SonataAdminBundle

The missing Symfony Admin Generator
https://docs.sonata-project.org/projects/SonataAdminBundle
MIT License
2.11k stars 1.26k forks source link

ChoiceFieldMaskType unescaped choice value in related JS code #5637

Closed horo42 closed 5 years ago

horo42 commented 5 years ago

Subject

ChoiceFieldMaskType's JavaScript in its twig template doesn't escape the field value, which breaks the JS when said value contains backslashes.

Steps to reproduce

Create a Sonata Admin class and configure a form field to use the ChoiceFieldMaskType with choices config in the form of 'Label' => 'FQCN'.

Creating a new entity works properly but editing breaks the initial form render until a 'changed' event is dispatched by selecting a different option. This "fix" doesn't work when there is only one choice.

Related code in form_admin_fields.html.twig

            {% if value is empty %}
                choice_field_mask_show(showMaskChoiceEl.val());
            {% else %}
                choice_field_mask_show("{{ value }}");
            {% endif %}

https://github.com/sonata-project/SonataAdminBundle/blob/3.x/src/Resources/views/Form/form_admin_fields.html.twig#L549

Expected results

choice_field_mask_show("App\\Application\\Sonata\\UserBundle\\Entity\\User");

Actual results

choice_field_mask_show("App\Application\Sonata\UserBundle\Entity\User");

Recommendation

Replace choice_field_mask_show("{{ value }}"); with choice_field_mask_show("{{ value | e('js') }}");

phansys commented 5 years ago

Thank you so much for the report.

Could you please provide a code snippet from configureFormFields() showing the code required to reproduce the issue?

horo42 commented 5 years ago
$formMapper->add('choiceFieldMask', ChoiceFieldMaskType::class, [
    'mapped'  => false,
    'choices' => [
        'User'  => 'App\\Application\\Sonata\\UserBundle\\Entity\\User',
        'Media' => 'App\\Application\\Sonata\\MediaBundle\\Entity\\Media',
    ],
    'map'     => [
        'App\\Application\\Sonata\\UserBundle\\Entity\\User'   => ['User'],
        'App\\Application\\Sonata\\MediaBundle\\Entity\\Media' => ['Media'],
    ],
    'data' => 'App\\Application\\Sonata\\UserBundle\\Entity\\User',
]);

$formMapper->add('User', TextType::class, ['mapped' => false]);
$formMapper->add('Media', TextType::class, ['mapped' => false]);

The bug happens only if the ChoiceFieldMaskType field has a value already.

Without a pre-filled value, the script calls choice_field_mask_show(showMaskChoiceEl.val());

With a pre-filled value, the script calls choice_field_mask_show('App\Application\Sonata\UserBundle\Entity\User');

The former works because the value returned by .val() is already escaped. The proposed change in the OP fixed this issue for me.

phansys commented 5 years ago

Thanks @horo42, I could reproduce the issue and test the proposed fix :+1:

Could you please create a PR?

horo42 commented 5 years ago

Opened PR #5643