Skip to content

Commit

Permalink
Add support for Symfony 5.1 Compound constraint in form type guess (#36)
Browse files Browse the repository at this point in the history
  • Loading branch information
yann-eugone authored Sep 28, 2020
1 parent cdfbce5 commit 17e669f
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 13 deletions.
26 changes: 23 additions & 3 deletions src/Form/Extension/EnumTypeGuesser.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Symfony\Component\Form\Guess\TypeGuess;
use Symfony\Component\Form\Guess\ValueGuess;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Constraints\Compound;
use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface;
use Yokai\EnumBundle\EnumRegistry;
use Yokai\EnumBundle\Form\Type\EnumType;
Expand Down Expand Up @@ -40,15 +41,16 @@ public function __construct(MetadataFactoryInterface $metadataFactory, EnumRegis
*/
public function guessTypeForConstraint(Constraint $constraint): ?TypeGuess
{
if (!$constraint instanceof Enum) {
$enum = $this->getEnum($constraint);
if ($enum === null) {
return null;
}

return new TypeGuess(
EnumType::class,
[
'enum' => $constraint->enum,
'multiple' => $constraint->multiple,
'enum' => $enum->enum,
'multiple' => $enum->multiple,
],
Guess::HIGH_CONFIDENCE
);
Expand Down Expand Up @@ -77,4 +79,22 @@ public function guessPattern($class, $property): ?ValueGuess
{
return null; //override parent : not able to guess
}

private function getEnum(Constraint $constraint): ?Enum
{
if ($constraint instanceof Enum) {
return $constraint;
}

if ($constraint instanceof Compound) {
foreach ($constraint->constraints as $compositeConstraint) {
$enum = $this->getEnum($compositeConstraint);
if ($enum !== null) {
return $enum;
}
}
}

return null;
}
}
49 changes: 39 additions & 10 deletions tests/Form/Extension/EnumTypeGuesserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Symfony\Component\Form\Guess\Guess;
use Symfony\Component\Form\Guess\TypeGuess;
use Symfony\Component\Form\Test\TypeTestCase;
use Symfony\Component\Validator\Constraints\Compound;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface;
use Yokai\EnumBundle\EnumRegistry;
Expand All @@ -26,7 +27,8 @@ class EnumTypeGuesserTest extends TypeTestCase

const TEST_CLASS = EnumTypeGuesserTest_TestClass::class;

const TEST_PROPERTY = 'property';
const TEST_PROPERTY_DIRECT = 'direct';
const TEST_PROPERTY_COMPOUND = 'compound';

/**
* @var EnumTypeGuesser
Expand Down Expand Up @@ -56,7 +58,15 @@ protected function setUp(): void
$this->enumRegistry->get(GenderEnum::class)->willReturn(new GenderEnum);

$this->metadata = new ClassMetadata(self::TEST_CLASS);
$this->metadata->addPropertyConstraint(self::TEST_PROPERTY, new Enum(['enum' => GenderEnum::class]));
$this->metadata->addPropertyConstraint(self::TEST_PROPERTY_DIRECT, new Enum(['enum' => GenderEnum::class]));
if (class_exists(Compound::class)) {
$this->metadata->addPropertyConstraint(self::TEST_PROPERTY_COMPOUND, new class extends Compound {
protected function getConstraints(array $options): array
{
return [new Enum(['enum' => GenderEnum::class])];
}
});
}
$this->metadataFactory = $this->prophesize(MetadataFactoryInterface::class);
$this->metadataFactory->getMetadataFor(self::TEST_CLASS)
->willReturn($this->metadata);
Expand All @@ -66,7 +76,7 @@ protected function setUp(): void
parent::setUp();
}

public function testGuessType(): void
public function testGuessTypeDirect(): void
{
$guess = new TypeGuess(
EnumType::class,
Expand All @@ -77,33 +87,51 @@ public function testGuessType(): void
Guess::HIGH_CONFIDENCE
);

$this->assertEquals($guess, $this->guesser->guessType(self::TEST_CLASS, self::TEST_PROPERTY));
$this->assertEquals($guess, $this->guesser->guessType(self::TEST_CLASS, self::TEST_PROPERTY_DIRECT));
}

public function testGuessTypeCompound(): void
{
if (!class_exists(Compound::class)) {
$this->markTestSkipped();
}

$guess = new TypeGuess(
EnumType::class,
[
'enum' => GenderEnum::class,
'multiple' => false,
],
Guess::HIGH_CONFIDENCE
);

$this->assertEquals($guess, $this->guesser->guessType(self::TEST_CLASS, self::TEST_PROPERTY_COMPOUND));
}

public function testGuessRequired(): void
{
$this->assertNull($this->guesser->guessRequired(self::TEST_CLASS, self::TEST_PROPERTY));
$this->assertNull($this->guesser->guessRequired(self::TEST_CLASS, self::TEST_PROPERTY_DIRECT));
}

public function testGuessMaxLength(): void
{
$this->assertNull($this->guesser->guessMaxLength(self::TEST_CLASS, self::TEST_PROPERTY));
$this->assertNull($this->guesser->guessMaxLength(self::TEST_CLASS, self::TEST_PROPERTY_DIRECT));
}

public function testGuessPattern(): void
{
$this->assertNull($this->guesser->guessPattern(self::TEST_CLASS, self::TEST_PROPERTY));
$this->assertNull($this->guesser->guessPattern(self::TEST_CLASS, self::TEST_PROPERTY_DIRECT));
}

public function testCreateForm(): void
{
$class = self::TEST_CLASS;
$form = $this->factory->create(FormType::class, new $class, ['data_class' => $class])
->add(self::TEST_PROPERTY);
->add(self::TEST_PROPERTY_DIRECT);

$this->assertEquals(
['Male' => 'male', 'Female' => 'female'],
$form->get(self::TEST_PROPERTY)->getConfig()->getOption('choices')
$form->get(self::TEST_PROPERTY_DIRECT)->getConfig()->getOption('choices')
);
}

Expand All @@ -117,5 +145,6 @@ protected function getExtensions(): array

class EnumTypeGuesserTest_TestClass
{
public $property;
public $direct;
public $compound;
}

0 comments on commit 17e669f

Please sign in to comment.