Skip to content

Commit

Permalink
Attributes for custom Postgre type names, PHP>=8.2 required
Browse files Browse the repository at this point in the history
  • Loading branch information
egbuk committed Jan 10, 2025
1 parent 4378bb8 commit 5e07206
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 26 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# Doctrine enums for PostgreSQL
[![Version](https://poser.pugx.org/heymoon/doctrine-psql-enum/v)](https://packagist.org/packages/heymoon/doctrine-psql-enum)
[![PHP Version Require](https://poser.pugx.org/heymoon/doctrine-psql-enum/require/php)](https://packagist.org/packages/heymoon/doctrine-psql-enum)
[![Test](https://github.com/heymoon-cc/doctrine-psql-enum/actions/workflows/test.yaml/badge.svg)](https://github.com/heymoon-cc/doctrine-psql-enum/actions/workflows/test.yaml)
## Prerequisites: *Symfony 7 + Doctrine 3*

Expand Down
6 changes: 3 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"name": "heymoon/doctrine-psql-enum",
"version": "2.0.0",
"description": "Store PHP8.1 native enums as PostgeSQL custom enum types",
"version": "2.1.0",
"description": "Store PHP native enums as PostgeSQL custom enum types",
"type": "symfony-bundle",
"license": "MIT",
"keywords": ["doctrine-orm", "postgresql", "enum"],
"require": {
"php": ">=8.1",
"php": ">=8.2",
"doctrine/doctrine-bundle": "2.*",
"doctrine/orm": "3.*",
"symfony/framework-bundle": "7.*"
Expand Down
18 changes: 18 additions & 0 deletions src/Attribute/EnumType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace HeyMoon\DoctrinePostgresEnum\Attribute;

use Attribute;

#[Attribute(Attribute::TARGET_CLASS)]
final readonly class EnumType
{
public function __construct(
private string $name
) {}

public function getName(): string
{
return $this->name;
}
}
2 changes: 1 addition & 1 deletion src/DependencyInjection/DoctrinePostgresEnumExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class DoctrinePostgresEnumExtension extends Extension implements PrependExtensio
/**
* @throws Exception
*/
public function load(array $configs, ContainerBuilder $container)
public function load(array $configs, ContainerBuilder $container): void
{
$configuration = $this->getConfiguration($configs, $container);
$cfg = $this->processConfiguration($configuration, $configs);
Expand Down
7 changes: 3 additions & 4 deletions src/Doctrine/Listener/DoctrineEnumColumnListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Schema\ColumnDiff;
use ReflectionException;
use StringBackedEnum;
use UnitEnum;

Expand Down Expand Up @@ -50,7 +49,7 @@ public function postConnect(ConnectionEventArgs $event): void
}

/**
* @throws Exception|ReflectionException
* @throws Exception
* @noinspection PhpUnused
*/
public function onSchemaCreateTable(SchemaCreateTableEventArgs $event): void
Expand Down Expand Up @@ -137,7 +136,7 @@ public function onSchemaColumnDefinition(SchemaColumnDefinitionEventArgs $event)
}

/**
* @throws ReflectionException|Exception
* @throws Exception
* @noinspection PhpUnused
*/
public function onSchemaAlterTable(SchemaAlterTableEventArgs $event): void
Expand Down Expand Up @@ -242,7 +241,7 @@ protected function dumpComments(AbstractPlatform $platform): array
}

/**
* @throws ReflectionException|Exception
* @throws Exception
*/
protected function processColumn(string $tableName, array $column, AbstractPlatform $platform, bool $alter = false): array
{
Expand Down
25 changes: 19 additions & 6 deletions src/Doctrine/Type/EnumType.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@

use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\Type;
use ReflectionAttribute;
use ReflectionEnum;
use ReflectionException;
use Doctrine\DBAL\Exception;
use UnitEnum;
use HeyMoon\DoctrinePostgresEnum\Attribute\EnumType as EnumTypeAttribute;

class EnumType extends Type
{
Expand Down Expand Up @@ -41,20 +44,26 @@ public static function comment(string $type): string
return "($tag:$type)";
}

/**
* @throws Exception
*/
public static function nameFromClass(string $class): string
{
return
$attributes = static::getReflection($class)->getAttributes(EnumTypeAttribute::class);
/** @var ReflectionAttribute $attribute */
$attribute = reset($attributes);
return $attributes ? $attribute->getArguments()[0] :
str_replace('\\', '_', strtolower($class));
}

/**
* @throws ReflectionException
* @throws Exception
*/
public function getSQLDeclaration(array $column, AbstractPlatform $platform): string
{
$class = null;
if ($column['enumType'] ?? null) {
$class = $this->getReflection($column['enumType'])->getName();
$class = static::getReflection($column['enumType'])->getName();
} elseif ($column['comment'] ?? null) {
$class = static::parseComment($column['comment']);
}
Expand Down Expand Up @@ -91,10 +100,14 @@ public function getName(): string
}

/**
* @throws ReflectionException
* @throws Exception
*/
protected function getReflection(string $enumType): ReflectionEnum
protected static function getReflection(string $enumType): ReflectionEnum
{
return new ReflectionEnum($enumType);
try {
return new ReflectionEnum($enumType);
} catch (ReflectionException $e) {
throw new Exception($e->getMessage(), $e->getCode(), $e);
}
}
}
12 changes: 12 additions & 0 deletions tests/Fixtures/Enum/ExampleAttributeEnum.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace HeyMoon\DoctrinePostgresEnum\Tests\Fixtures\Enum;

use HeyMoon\DoctrinePostgresEnum\Attribute\EnumType;

#[EnumType('example')]
enum ExampleAttributeEnum: string
{
case Test = 'test';
case Case = 'case';
}
7 changes: 7 additions & 0 deletions tests/Fixtures/Enum/ExampleInvalidEnum.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace Fixtures\Enum;

final class ExampleInvalidEnum
{
}
38 changes: 26 additions & 12 deletions tests/Unit/EnumTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,19 @@
namespace HeyMoon\DoctrinePostgresEnum\Tests\Unit;

use Doctrine\DBAL\Exception;
use Fixtures\Enum\ExampleInvalidEnum;
use HeyMoon\DoctrinePostgresEnum\Doctrine\Type\EnumType;
use HeyMoon\DoctrinePostgresEnum\Tests\BaseTestCase;
use HeyMoon\DoctrinePostgresEnum\Tests\Fixtures\Enum\ExampleAttributeEnum;
use HeyMoon\DoctrinePostgresEnum\Tests\Fixtures\Enum\ExampleEnum;

final class EnumTypeTest extends BaseTestCase
{
private const NAMES = [
ExampleEnum::class => 'heymoon_doctrinepostgresenum_tests_fixtures_enum_exampleenum',
ExampleAttributeEnum::class => 'example'
];

/**
* @covers EnumType::setCommentTag
* @covers EnumType::getCommentTag
Expand All @@ -19,21 +26,28 @@ final class EnumTypeTest extends BaseTestCase
*/
public function testEnumType(): void
{
$tag = 'TestTag';
EnumType::setCommentTag($tag);
$this->assertEquals($tag, EnumType::getCommentTag());
$class = ExampleEnum::class;
$type = EnumType::getType(EnumType::getDefaultName());
$platform = $this->getPlatform();
$this->assertEquals(EnumType::nameFromClass($class),
$type->getSQLDeclaration(['enumType' => $class], $platform)
);
$comment = EnumType::comment($class);
$this->assertEquals("($tag:$class)", $comment);
$this->assertEquals($class, EnumType::parseComment($comment));
EnumType::setCommentTag('Broken');
$this->assertNull(EnumType::parseComment($comment));
$tag = 'TestTag';
foreach ([ExampleEnum::class, ExampleAttributeEnum::class] as $class) {
EnumType::setCommentTag($tag);
$this->assertEquals($tag, EnumType::getCommentTag());
$this->assertEquals(self::NAMES[$class], EnumType::nameFromClass($class));
$this->assertEquals(self::NAMES[$class],
$type->getSQLDeclaration(['enumType' => $class], $platform)
);
$comment = EnumType::comment($class);
$this->assertEquals("($tag:$class)", $comment);
$this->assertEquals($class, EnumType::parseComment($comment));
$this->assertEquals(self::NAMES[$class],
$type->getSQLDeclaration(['comment' => $comment], $platform)
);
EnumType::setCommentTag('Broken');
$this->assertNull(EnumType::parseComment($comment));
}
$raw = 'raw';
$this->assertEquals($raw, $type->getSQLDeclaration(['rawType' => $raw], $platform));
$this->expectException(Exception::class);
$type->getSQLDeclaration(['enumType' => ExampleInvalidEnum::class], $platform);
}
}

0 comments on commit 5e07206

Please sign in to comment.