-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,100 +10,95 @@ | |
use Doctrine\DBAL\Platforms\SQLServerPlatform; | ||
use Doctrine\DBAL\Types\Exception\InvalidType; | ||
use Doctrine\DBAL\Types\Exception\ValueNotConvertible; | ||
use ReflectionClass; | ||
use Throwable; | ||
|
||
use function array_map; | ||
use function class_exists; | ||
use function implode; | ||
use function is_string; | ||
use function sprintf; | ||
|
||
final class EnumType extends Type | ||
{ | ||
public string $name = 'enum'; | ||
|
||
public ?string $enumClassname = null; | ||
|
||
/** @var array<int, string> */ | ||
public array $members = []; | ||
|
||
/** | ||
* Gets an array of database types that map to this Doctrine type. | ||
* | ||
* @return string[] | ||
* {@inheritDoc} | ||
*/ | ||
public function getMappedDatabaseTypes(AbstractPlatform $platform): array | ||
{ | ||
return [$this->name]; | ||
} | ||
|
||
/** | ||
* Gets the SQL declaration snippet for a field of this type. | ||
* | ||
* @param mixed[] $column The field declaration | ||
* @param AbstractPlatform $platform The currently used database platform | ||
* {@inheritDoc} | ||
*/ | ||
public function getSqlDeclaration(array $column, AbstractPlatform $platform): string | ||
{ | ||
assert($column['type'] instanceof self::class); | ||
|
||
$values = implode( | ||
', ', | ||
array_map( | ||
static fn (string $value) => "'{$value}'", | ||
$column['members'] ?: $column['type']->members | ||
) | ||
static fn (string $value) => sprintf('\'%s\'', $value), | ||
$column['members'] ?: $column['type']->members, | ||
), | ||
); | ||
|
||
$sqlDeclaration = match (true) { | ||
return match (true) { | ||
$platform instanceof SqlitePlatform => sprintf('TEXT CHECK(%s IN (%s))', $column['name'], $values), | ||
Check failure on line 53 in src/Types/EnumType.php GitHub Actions / Static Analysis with PHPStan (8.3)
Check failure on line 53 in src/Types/EnumType.php GitHub Actions / Static Analysis with Psalm (8.3)InvalidClass
|
||
$platform instanceof PostgreSqlPlatform, $platform instanceof SQLServerPlatform => sprintf('VARCHAR(255) CHECK(%s IN (%s))', $column['name'], $values), | ||
Check warning on line 54 in src/Types/EnumType.php GitHub Actions / Coding Standards / Coding Standards (8.3)
Check failure on line 54 in src/Types/EnumType.php GitHub Actions / Static Analysis with PHPStan (8.3)
Check failure on line 54 in src/Types/EnumType.php GitHub Actions / Static Analysis with Psalm (8.3)InvalidClass
|
||
default => sprintf('ENUM(%s)', $values), | ||
}; | ||
|
||
return $sqlDeclaration; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
* | ||
* @return mixed the database representation of the value | ||
* | ||
* @throws \InvalidArgumentException | ||
* {@inheritDoc} | ||
*/ | ||
public function convertToDatabaseValue($value, AbstractPlatform $platform): ?string | ||
{ | ||
if (null === $value) { | ||
if ($value === null) { | ||
return null; | ||
} | ||
|
||
return (string) $value; | ||
} | ||
|
||
/** | ||
Check failure on line 71 in src/Types/EnumType.php GitHub Actions / Coding Standards / Coding Standards (8.3)
|
||
* {@inheritdoc} | ||
* | ||
* @return mixed the PHP representation of the value | ||
* {@inheritDoc} | ||
*/ | ||
public function convertToPHPValue(mixed $value, AbstractPlatform $platform): mixed | ||
{ | ||
if (null === $value) { | ||
if ($value === null) { | ||
return null; | ||
} | ||
|
||
if (!\is_string($value)) { | ||
if (! is_string($value)) { | ||
throw InvalidType::new($value, $this->name, ['null', 'string']); | ||
} | ||
|
||
$refl = new \ReflectionClass($this->enumClassname); | ||
if ($this->enumClassname && class_exists($this->enumClassname)) { | ||
Check failure on line 84 in src/Types/EnumType.php GitHub Actions / Static Analysis with PHPStan (8.3)
Check failure on line 84 in src/Types/EnumType.php GitHub Actions / Static Analysis with Psalm (8.3)RiskyTruthyFalsyComparison
|
||
$refl = new ReflectionClass($this->enumClassname); | ||
|
||
try { | ||
return $refl->newInstance($value); | ||
} catch (\Throwable $e) { | ||
throw ValueNotConvertible::new($value, $this->name, $e->getMessage(), $e); | ||
try { | ||
return $refl->newInstance($value); | ||
} catch (Throwable $e) { | ||
throw ValueNotConvertible::new($value, $this->name, $e->getMessage(), $e); | ||
} | ||
} | ||
|
||
return $value; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public static function addType(string $name, string $enumClassname): void | ||
Check failure on line 97 in src/Types/EnumType.php GitHub Actions / Static Analysis with Psalm (8.3)ParamNameMismatch
|
||
{ | ||
self::getTypeRegistry()->register($name, $me = new self()); | ||
$me->name = $name; | ||
$me->name = $name; | ||
$me->enumClassname = $enumClassname; | ||
$me->members = $enumClassname::getAllowedValues(); | ||
$me->members = $enumClassname::getAllowedValues(); | ||
Check failure on line 102 in src/Types/EnumType.php GitHub Actions / Static Analysis with PHPStan (8.3)
Check failure on line 102 in src/Types/EnumType.php GitHub Actions / Static Analysis with Psalm (8.3)UndefinedMethod
|
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Doctrine\DBAL\Tests\Types; | ||
|
||
use Doctrine\DBAL\Platforms\AbstractPlatform; | ||
use Doctrine\DBAL\Types\EnumType; | ||
use PHPUnit\Framework\MockObject\MockObject; | ||
use PHPUnit\Framework\TestCase; | ||
|
||
use function anonymous_class; | ||
Check failure on line 12 in tests/Types/EnumTest.php GitHub Actions / Coding Standards / Coding Standards (8.3)
|
||
|
||
class EnumTest extends TestCase | ||
{ | ||
private AbstractPlatform&MockObject $platform; | ||
private EnumType $type; | ||
|
||
protected function setUp(): void | ||
{ | ||
$this->platform = $this->createMock(AbstractPlatform::class); | ||
$this->type = new EnumType(); | ||
} | ||
|
||
public function testReturnsSQLDeclaration(): void | ||
{ | ||
self::assertEquals('ENUM(\'A\', \'B\')', $this->type->getSQLDeclaration(['members' => ['A', 'B']], $this->platform)); | ||
Check warning on line 27 in tests/Types/EnumTest.php GitHub Actions / Coding Standards / Coding Standards (8.3)
|
||
} | ||
|
||
public function testConvertToPHPValue(): void | ||
{ | ||
self::assertIsString($this->type->convertToPHPValue('foo', $this->platform)); | ||
self::assertIsString($this->type->convertToPHPValue('', $this->platform)); | ||
self::assertNull($this->type->convertToPHPValue(null, $this->platform)); | ||
} | ||
|
||
public function testConvertToPHPObject(): void | ||
{ | ||
$this->type->enumClassname = get_class(self::getEnumClass()); | ||
|
||
self::assertInstanceOf($this->type->enumClassname, $this->type->convertToPHPValue('A', $this->platform)); | ||
self::assertEquals('A', $this->type->convertToPHPValue('A', $this->platform)->getValue()); | ||
} | ||
|
||
public function testConvertStringToDatabaseValue(): void | ||
{ | ||
self::assertEquals('A', $this->type->convertToDatabaseValue('A', $this->platform)); | ||
self::assertNull($this->type->convertToDatabaseValue(null, $this->platform)); | ||
} | ||
|
||
public function testConvertObjectToDatabaseValue(): void | ||
{ | ||
$enum = self::getEnumClass('A'); | ||
$this->type->enumClassname = get_class(self::getEnumClass()); | ||
|
||
self::assertEquals('A', $this->type->convertToDatabaseValue($enum, $this->platform)); | ||
self::assertNull($this->type->convertToDatabaseValue(null, $this->platform)); | ||
} | ||
|
||
private static function getEnumClass(mixed $value = null) | ||
Check failure on line 60 in tests/Types/EnumTest.php GitHub Actions / Static Analysis with Psalm (8.3)MissingReturnType
|
||
{ | ||
return new class ($value) implements \Stringable { | ||
function __construct( | ||
private ?string $value | ||
) { | ||
} | ||
|
||
function getValue(): ?string | ||
{ | ||
return $this->value; | ||
} | ||
|
||
function __tostring(): string | ||
{ | ||
return $this->value; | ||
Check failure on line 75 in tests/Types/EnumTest.php GitHub Actions / Static Analysis with Psalm (8.3)NullableReturnStatement
|
||
} | ||
}; | ||
} | ||
} |