Skip to content

Commit

Permalink
PHP enums support receiving the enum value to convert to DB
Browse files Browse the repository at this point in the history
Because Doctrine ORM might implicitly convert an enum object to its
value, it might happen that our type receives the enum value, instead of
the object. In that case, our type should do nothing and return the
given value (as long as it is a valid value).
  • Loading branch information
PowerKiKi committed Jul 8, 2024
1 parent 2b5abdb commit b093e15
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 22 deletions.
4 changes: 4 additions & 0 deletions src/DBAL/Types/PhpEnumType.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ public function convertToDatabaseValue(mixed $value, AbstractPlatform $platform)
return null;
}

if (is_string($value) && $this->getEnumType()::tryFrom($value)) {
return $value;
}

if (!is_object($value) || !is_a($value, $this->getEnumType())) {
throw new InvalidArgumentException("Invalid '" . Utils::printSafe($value) . "' value to be stored in database for enum " . $this->getName());
}
Expand Down
62 changes: 40 additions & 22 deletions tests/DBAL/Types/PhpEnumTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,50 +34,68 @@ protected function getEnumType(): string
public function testEnum(): void
{
self::assertSame("ENUM('value1', 'value2')", $this->type->getSqlDeclaration(['foo'], $this->platform));

// Should always return string
self::assertSame(TestEnum::key1, $this->type->convertToPHPValue('value1', $this->platform));

// Should support null values or empty string
self::assertNull($this->type->convertToPHPValue(null, $this->platform));
self::assertNull($this->type->convertToPHPValue('', $this->platform));
self::assertNull($this->type->convertToDatabaseValue(null, $this->platform));

self::assertTrue($this->type->requiresSQLCommentHint($this->platform));
}

public function testConvertToPHPValueThrowsWithInvalidValue(): void
/**
* @dataProvider providerConvertToPHPValue
*/
public function testConvertToPHPValue(?string $input, ?TestEnum $expected): void
{
$this->expectException(ValueError::class);
self::assertSame($expected, $this->type->convertToPHPValue($input, $this->platform));
}

$this->type->convertToPHPValue('foo', $this->platform);
public function providerConvertToPHPValue(): iterable
{
yield ['value1', TestEnum::key1];
yield [null, null];
yield ['', null];
}

public function testConvertToDatabaseValueThrowsWithInvalidValue(): void
/**
* @dataProvider providerConvertToDatabaseValue
*/
public function testConvertToDatabaseValue(mixed $input, ?string $expected): void
{
$this->expectException(InvalidArgumentException::class);
self::assertSame($expected, $this->type->convertToDatabaseValue($input, $this->platform));
}

$this->type->convertToDatabaseValue('foo', $this->platform);
public function providerConvertToDatabaseValue(): iterable
{
yield [null, null];
yield [TestEnum::key1, 'value1'];
yield ['value1', 'value1'];
}

public function testConvertToDatabaseValueThrowsWithInvalidEnum(): void
/**
* @dataProvider providerInvalidConvertToDatabaseValue
*/
public function testInvalidConvertToDatabaseValue(mixed $input): void
{
$this->expectException(InvalidArgumentException::class);

$this->type->convertToDatabaseValue(OtherTestEnum::key1, $this->platform);
$this->type->convertToDatabaseValue($input, $this->platform);
}

public function testConvertToPHPValueThrowsWithZero(): void
public function providerInvalidConvertToDatabaseValue(): iterable
{
$this->expectException(InvalidArgumentException::class);
yield ['foo'];
yield ['key1'];
yield [OtherTestEnum::key1];
yield [0];
}

$this->type->convertToPHPValue(0, $this->platform);
public function testConvertToPHPValueThrowsWithInvalidValue(): void
{
$this->expectException(ValueError::class);

$this->type->convertToPHPValue('foo', $this->platform);
}

public function testConvertToDatabaseValueThrowsWithZero(): void
public function testConvertToPHPValueThrowsWithZero(): void
{
$this->expectException(InvalidArgumentException::class);

$this->type->convertToDatabaseValue(0, $this->platform);
$this->type->convertToPHPValue(0, $this->platform);
}
}

0 comments on commit b093e15

Please sign in to comment.