Skip to content

Commit

Permalink
[Form] Filter arrays out of scalar form types
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolas-grekas committed Dec 7, 2018
1 parent 9e84e0f commit 000e4aa
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 12 deletions.
7 changes: 4 additions & 3 deletions src/Symfony/Component/Form/Form.php
Expand Up @@ -532,11 +532,12 @@ public function submit($submittedData, $clearMissing = true)
$submittedData = null;
} elseif (is_scalar($submittedData)) {
$submittedData = (string) $submittedData;
} elseif ($this->config->getOption('allow_file_upload')) {
// no-op
} elseif ($this->config->getRequestHandler()->isFileUpload($submittedData)) {
} elseif (!$this->config->getOption('allow_file_upload') && $this->config->getRequestHandler()->isFileUpload($submittedData)) {
$submittedData = null;
$this->transformationFailure = new TransformationFailedException('Submitted data was expected to be text or number, file upload given.');
} elseif (\is_array($submittedData) && !$this->config->getCompound() && !$this->config->hasOption('multiple')) {

This comment has been minimized.

Copy link
@quantizer

quantizer Jan 8, 2019

@nicolas-grekas hello,

I’m using the form for JSON validation in my project, so I do json decode of request content and do form->submit with this array. But after this update one of my fields, which array of arrays failed with Submitted data was expected to be text or number, array given.

Here is an example of what I try to set in a field:

"products_quantity" => [                                            
        [                                                             
            "product_id": "ID",     
            "quantity": 10                                            
        ],                                                            
        [                                                             
            "product_id": "ID",     
            "quantity": 3                                             
        ]                                                             
    ],

I tried to use choice field type with multiple true parameter. But values could be only strings or numbers. Because this is feature of submit method custom field type and transformers won't help in this situation. So looks like I need to change input format?

This comment has been minimized.

Copy link
@nicolas-grekas

nicolas-grekas Jan 8, 2019

Author Member

That's correct.

This comment has been minimized.

Copy link
@ewgRa

ewgRa Jan 18, 2019

Contributor

Same problem here. We try to send an array to $builder->add('settings')

Looks like broken backward compatibility. How now we can achieve it?

This comment has been minimized.

Copy link
@xabbuh

xabbuh Jan 18, 2019

Member

please read #29809, #29841, #29905 and #29911

This comment has been minimized.

Copy link
@vkurdin

vkurdin Jan 23, 2019

@nicolas-grekas @xabbuh !$this->config->hasOption('multiple') check is fixed to specific option that can be found only in ChoiceType options. Doesn't It look like some inconsistency: generic form code(submit method) is tied down to option from some specific form type? Maybe add this option to the topmost FormType?

I'm also not a big fan of introducing another option like proposed in #29911, that can lead to exceeding complexity to understand what values may or not be handled by superposition of completely unrelated options.

This comment has been minimized.

Copy link
@apfelbox

apfelbox Jan 23, 2019

Contributor

@quantizer looks like your field for products_quantity must be of type collection, that includes a nested form with the product_id and quantity fields.

This comment has been minimized.

Copy link
@quantizer

quantizer Jan 23, 2019

@apfelbox yup, i did like this with collection type:

"products_quantity": {
    "b86e89a1-d74b-11e8-8cbb-0242ac160002": 10,
},
$submittedData = null;
$this->transformationFailure = new TransformationFailedException('Submitted data was expected to be text or number, array given.');
}

$dispatcher = $this->config->getEventDispatcher();
Expand Down
16 changes: 16 additions & 0 deletions src/Symfony/Component/Form/Tests/CompoundFormTest.php
Expand Up @@ -1036,6 +1036,22 @@ public function testDisabledButtonIsNotSubmitted()
$this->assertFalse($submit->isSubmitted());
}

public function testArrayTransformationFailureOnSubmit()
{
$this->form->add($this->getBuilder('foo')->setCompound(false)->getForm());
$this->form->add($this->getBuilder('bar', null, null, array('multiple' => false))->setCompound(false)->getForm());

$this->form->submit(array(
'foo' => array('foo'),
'bar' => array('bar'),
));

$this->assertNull($this->form->get('foo')->getData());
$this->assertSame('Submitted data was expected to be text or number, array given.', $this->form->get('foo')->getTransformationFailure()->getMessage());

$this->assertSame(array('bar'), $this->form->get('bar')->getData());
}

public function testFileUpload()
{
$reqHandler = new HttpFoundationRequestHandler();
Expand Down
Expand Up @@ -83,14 +83,6 @@ public function testThrowExceptionIfDefaultProtocolIsInvalid()
));
}

public function testSubmitWithNonStringDataDoesNotBreakTheFixUrlProtocolListener()
{
$form = $this->factory->create(static::TESTED_TYPE);
$form->submit(array('domain.com', 'www.domain.com'));

$this->assertSame(array('domain.com', 'www.domain.com'), $form->getData());
}

public function testSubmitNullUsesDefaultEmptyData($emptyData = 'empty', $expectedData = 'http://empty')
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
Expand Down
Expand Up @@ -220,7 +220,7 @@ public function testDontValidateConstraintsIfNoValidationGroups()
->getForm();

// Launch transformer
$form->submit(array());
$form->submit('foo');

$this->expectNoValidate();

Expand Down

0 comments on commit 000e4aa

Please sign in to comment.