diff --git a/src/Annotation/Column.php b/src/Annotation/Column.php index cf5aad86..6e25c45f 100644 --- a/src/Annotation/Column.php +++ b/src/Annotation/Column.php @@ -73,7 +73,7 @@ public function __construct( if ($default !== null) { $this->hasDefault = true; } - $this->attributes = $attributes; + $this->setAttributes($attributes); } /** @@ -142,4 +142,33 @@ public function getAttributes(): array { return $this->attributes; } + + protected function setAttributes(array $attributes): void + { + if ($this->type === 'enum' && isset($attributes['values'])) { + /** @var mixed $values */ + $values = $attributes['values']; + /** @var list $array */ + $array = []; + + if (is_string($values) && enum_exists($values) && method_exists($values, 'cases')) { + /** @var class-string<\BackedEnum> $values */ + $array = array_column($values::cases(), 'value'); + } elseif ($values instanceof \BackedEnum) { + $array = array_column($values::cases(), 'value'); + } elseif (is_array($values)) { + $array = array_map(function ($value) { + return $value instanceof \BackedEnum ? $value->value : $value; + }, $values); + } + + $this->type = 'enum(' . implode(',', array_map(function ($item) { + return is_scalar($item) ? strval($item) : ''; + }, $array)) . ')'; + + unset($attributes['values']); + } + + $this->attributes = $attributes; + } } diff --git a/tests/Annotated/Unit/Attribute/ColumnTest.php b/tests/Annotated/Unit/Attribute/ColumnTest.php index 613742be..3cd18048 100644 --- a/tests/Annotated/Unit/Attribute/ColumnTest.php +++ b/tests/Annotated/Unit/Attribute/ColumnTest.php @@ -5,10 +5,14 @@ namespace Cycle\Annotated\Tests\Unit\Attribute; use Cycle\Annotated\Annotation\Column; +use Cycle\Annotated\Tests\Unit\Attribute\SingleTable\StringEnum; use PHPUnit\Framework\TestCase; class ColumnTest extends TestCase { + public const ENUM_VALUE_A = 'a'; + public const ENUM_VALUE_B = 'b'; + #[Column('integer', nullable: true, unsigned: true)] private $column1; @@ -21,42 +25,101 @@ class ColumnTest extends TestCase #[Column('string(32)', readonlySchema: true)] private mixed $column4; + #[Column(type: 'enum(a,b)')] + private string $column5; + + #[Column( + type: 'enum', + default: self::ENUM_VALUE_A, + values: [self::ENUM_VALUE_A, self::ENUM_VALUE_B], + )] + private string $column6 = self::ENUM_VALUE_A; + + #[Column( + type: 'enum', + default: 'a', + typecast: StringEnum::class, + values: StringEnum::class, + )] + private StringEnum $column7 = StringEnum::A; + + #[Column( + type: 'enum', + default: 'a', + values: [StringEnum::A, StringEnum::B], + )] + private string $column8 = 'a'; + public function testOneAttribute(): void { - $attr = $this->getAttribute('column1'); + $column = $this->getColumn('column1'); - $this->assertSame(['unsigned' => true], $attr->getAttributes()); + $this->assertSame(['unsigned' => true], $column->getAttributes()); } public function testTwoAttributes(): void { - $attr = $this->getAttribute('column2'); + $column = $this->getColumn('column2'); - $this->assertSame(['unsigned' => true, 'zerofill' => true], $attr->getAttributes()); + $this->assertSame(['unsigned' => true, 'zerofill' => true], $column->getAttributes()); } public function testCustomSizeAttribute(): void { - $attr = $this->getAttribute('column3'); + $column = $this->getColumn('column3'); - $this->assertSame(['size' => 128], $attr->getAttributes()); + $this->assertSame(['size' => 128], $column->getAttributes()); } public function testDefaultReadonlySchema(): void { - $attr = $this->getAttribute('column1'); + $column = $this->getColumn('column1'); - $this->assertFalse($attr->isReadonlySchema()); + $this->assertFalse($column->isReadonlySchema()); } public function testReadonlySchema(): void { - $attr = $this->getAttribute('column4'); + $column = $this->getColumn('column4'); + + $this->assertTrue($column->isReadonlySchema()); + } + + public function testEnumTypeString(): void + { + $column = $this->getColumn('column5'); + + $this->assertSame('enum(a,b)', $column->getType()); + } + + public function testEnumTypeArray(): void + { + $column = $this->getColumn('column6'); + + $this->assertSame('enum(a,b)', $column->getType()); + $this->assertSame('a', $column->getDefault()); + $this->assertArrayNotHasKey('values', $column->getAttributes()); + } + + public function testEnumTypeBackedEnum(): void + { + $column = $this->getColumn('column7'); + + $this->assertSame('enum(a,b)', $column->getType()); + $this->assertSame('a', $column->getDefault()); + $this->assertArrayNotHasKey('values', $column->getAttributes()); + } + + public function testEnumTypeArrayBackedEnum(): void + { + $column = $this->getColumn('column8'); - $this->assertTrue($attr->isReadonlySchema()); + $this->assertSame('enum(a,b)', $column->getType()); + $this->assertSame('a', $column->getDefault()); + $this->assertArrayNotHasKey('values', $column->getAttributes()); } - private function getAttribute(string $field): Column + private function getColumn(string $field): Column { $ref = new \ReflectionClass(static::class); return $ref->getProperty($field)->getAttributes(Column::class)[0]->newInstance();