Skip to content

Commit

Permalink
RepeatedType should always have inner types mapped
Browse files Browse the repository at this point in the history
  • Loading branch information
biozshock committed Apr 10, 2020
1 parent 932a4f8 commit 7cfe1fe
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 2 deletions.
20 changes: 18 additions & 2 deletions src/Symfony/Component/Form/Extension/Core/Type/RepeatedType.php
Expand Up @@ -12,6 +12,7 @@
namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Exception\InvalidConfigurationException;
use Symfony\Component\Form\Extension\Core\DataTransformer\ValueToDuplicatesTransformer;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
Expand All @@ -36,8 +37,8 @@ public function buildForm(FormBuilderInterface $builder, array $options)
$options['first_name'],
$options['second_name'],
]))
->add($options['first_name'], $options['type'], array_merge($options['options'], $options['first_options']))
->add($options['second_name'], $options['type'], array_merge($options['options'], $options['second_options']))
->add($options['first_name'], $options['type'], $this->mergeOptions($options['options'], $options['first_options']))
->add($options['second_name'], $options['type'], $this->mergeOptions($options['options'], $options['second_options']))
;
}

Expand Down Expand Up @@ -68,4 +69,19 @@ public function getBlockPrefix()
{
return 'repeated';
}

private function mergeOptions(array $fieldOptions, array $innerOptions)
{
$mergedOptions = array_merge($fieldOptions, $innerOptions);

if (\array_key_exists('mapped', $mergedOptions)) {
if (false === $mergedOptions['mapped']) {
throw new InvalidConfigurationException('Inner types must be mapped.');
}
} else {
$mergedOptions['mapped'] = true;
}

return $mergedOptions;
}
}
Expand Up @@ -11,7 +11,9 @@

namespace Symfony\Component\Form\Tests\Extension\Core\Type;

use Symfony\Component\Form\Exception\InvalidConfigurationException;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\Tests\Fixtures\NotMappedType;

class RepeatedTypeTest extends BaseTypeTest
{
Expand Down Expand Up @@ -78,6 +80,19 @@ public function testSetRequired()
$this->assertFalse($form['second']->isRequired());
}

public function testMappedOverridesDefault()
{
$form = $this->factory->create(NotMappedType::class);
$this->assertFalse($form->getConfig()->getMapped());

$form = $this->factory->create(static::TESTED_TYPE, null, [
'type' => NotMappedType::class,
]);

$this->assertTrue($form['first']->getConfig()->getMapped());
$this->assertTrue($form['second']->getConfig()->getMapped());
}

public function testSetInvalidOptions()
{
$this->expectException('Symfony\Component\OptionsResolver\Exception\InvalidOptionsException');
Expand Down Expand Up @@ -105,6 +120,29 @@ public function testSetInvalidSecondOptions()
]);
}

/**
* @param string $configurationKey
* @dataProvider notMappedConfigurationKeys
*/
public function testNotMappedInner($configurationKey)
{
$this->expectException(InvalidConfigurationException::class);
$this->expectExceptionMessage('Inner types must be mapped');

$this->factory->create(static::TESTED_TYPE, null, [
'type' => TextTypeTest::TESTED_TYPE,
$configurationKey => ['mapped' => false],
]);
}

public function notMappedConfigurationKeys()
{
return [
['first_options'],
['second_options'],
];
}

public function testSetErrorBubblingToTrue()
{
$form = $this->factory->create(static::TESTED_TYPE, null, [
Expand Down
23 changes: 23 additions & 0 deletions src/Symfony/Component/Form/Tests/Fixtures/NotMappedType.php
@@ -0,0 +1,23 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Form\Tests\Fixtures;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;

class NotMappedType extends AbstractType
{
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefault('mapped', false);
}
}

0 comments on commit 7cfe1fe

Please sign in to comment.