Skip to content

Commit 6ff6c73

Browse files
committed
Add to EntityListColumn ability to use enums as a key
1 parent eda2b7a commit 6ff6c73

File tree

2 files changed

+105
-14
lines changed

2 files changed

+105
-14
lines changed

src/Columns/EntityListColumn.php

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@ public function cast(mixed $dbValue): array
1515
{
1616
if (is_string($dbValue)) {
1717
try {
18-
$dbValue = (array)\json_decode($dbValue, true, 512, JSON_THROW_ON_ERROR);
18+
$dbValue = (array)\json_decode(
19+
json: $dbValue,
20+
associative: true,
21+
flags: JSON_THROW_ON_ERROR,
22+
);
1923
} catch (\JsonException $e) {
2024
throw new EntityException($e->getMessage(), $e);
2125
}
@@ -28,7 +32,13 @@ public function cast(mixed $dbValue): array
2832
continue;
2933
}
3034
if ($this->subType && isset($entity->{$this->subType})) {
31-
$result[$entity->{$this->subType}] = $entity;
35+
$key = $entity->{$this->subType};
36+
if ($key instanceof \BackedEnum) {
37+
$key = $key->value;
38+
} elseif ($key instanceof \UnitEnum) {
39+
$key = $key->name;
40+
}
41+
$result[$key] = $entity;
3242
} else {
3343
$result[] = $entity;
3444
}
@@ -47,14 +57,20 @@ public function uncast(mixed $entityValue): string
4757
if ($item instanceof $this->type) {
4858
$data = $item->toArray();
4959
if ($this->subType && isset($data[$this->subType])) {
50-
$list[$data[$this->subType]] = $data;
60+
$key = $item->{$this->subType};
61+
if ($key instanceof \BackedEnum) {
62+
$key = $key->value;
63+
} elseif ($key instanceof \UnitEnum) {
64+
$key = $key->name;
65+
}
66+
$list[$key] = $data;
5167
} else {
5268
$list[] = $data;
5369
}
5470
}
5571
}
5672
try {
57-
return \json_encode($list, JSON_THROW_ON_ERROR);
73+
return json_encode($list, JSON_THROW_ON_ERROR);
5874
} catch (\JsonException $e) {
5975
throw new EntityException($e->getMessage(), $e);
6076
}
@@ -67,18 +83,11 @@ private function getEntity(mixed $data): ?AbstractEntity
6783
}
6884
/** @var class-string<AbstractEntity> $entityClass */
6985
$entityClass = $this->type;
70-
if ($data instanceof $entityClass) {
86+
if (is_object($data) && $data::class === $entityClass) {
7187
return $data;
7288
}
73-
if (!is_array($data)) {
74-
if (!is_string($data) || !$data) {
75-
return null;
76-
}
77-
try {
78-
$data = (array)\json_decode($data, true, 512, JSON_THROW_ON_ERROR);
79-
} catch (\JsonException) {
80-
return null;
81-
}
89+
if (!\is_array($data)) {
90+
return null;
8291
}
8392
return $entityClass::fromArray($data);
8493
}

tests/Columns/EntityListColumnTest.php

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
use Composite\Entity\AbstractEntity;
66
use Composite\Entity\Attributes\ListOf;
77
use Composite\Entity\Exceptions\EntityException;
8+
use Composite\Entity\Tests\TestStand\TestBackedStringEnum;
89
use Composite\Entity\Tests\TestStand\TestEntity;
910
use Composite\Entity\Tests\TestStand\TestSubEntity;
11+
use Composite\Entity\Tests\TestStand\TestUnitEnum;
1012

1113
final class EntityListColumnTest extends \PHPUnit\Framework\TestCase
1214
{
@@ -119,6 +121,46 @@ public function __construct(
119121
$this->assertInstanceOf(ListOf::class, $attribute);
120122
}
121123

124+
public function test_castWithUnitEnumKey(): void
125+
{
126+
$class = new class extends AbstractEntity {
127+
public function __construct(
128+
#[ListOf(TestEntity::class, 'unit_enum')]
129+
public ?array $column = null,
130+
) {}
131+
};
132+
133+
$entity = $class::fromArray([
134+
'column' => [
135+
TestUnitEnum::Foo->name => ['str' => 'UnitFoo', 'unit_enum' => TestUnitEnum::Foo->name],
136+
TestUnitEnum::Bar->name => ['str' => 'UnitBar', 'unit_enum' => TestUnitEnum::Bar->name],
137+
]
138+
]);
139+
$this->assertCount(2, $entity->column);
140+
$this->assertEquals( 'UnitFoo', $entity->column[TestUnitEnum::Foo->name]->str);
141+
$this->assertEquals('UnitBar', $entity->column[TestUnitEnum::Bar->name]->str);
142+
}
143+
144+
public function test_castWithBackedEnumKey(): void
145+
{
146+
$class = new class extends AbstractEntity {
147+
public function __construct(
148+
#[ListOf(TestEntity::class, 'backed_enum')]
149+
public ?array $column = null,
150+
) {}
151+
};
152+
153+
$entity = $class::fromArray([
154+
'column' => [
155+
TestBackedStringEnum::Foo->value => ['str' => 'BackedFoo', 'backed_enum' => TestBackedStringEnum::Foo->value],
156+
TestBackedStringEnum::Bar->value => ['str' => 'BackedBar', 'backed_enum' => TestBackedStringEnum::Bar->value],
157+
]
158+
]);
159+
$this->assertCount(2, $entity->column);
160+
$this->assertEquals( 'BackedFoo', $entity->column[TestBackedStringEnum::Foo->value]->str);
161+
$this->assertEquals('BackedBar', $entity->column[TestBackedStringEnum::Bar->value]->str);
162+
}
163+
122164
public static function uncast_dataProvider(): array
123165
{
124166
$sub1 = TestSubEntity::fromArray(['str' => 'foo', 'number' => 123]);
@@ -190,6 +232,46 @@ public function __construct(
190232
$this->assertEquals($expected, $actual);
191233
}
192234

235+
public function test_uncastWithUnitEnumKey(): void
236+
{
237+
$value = [
238+
TestUnitEnum::Foo->name => new TestEntity(str: 'UnitFoo', unit_enum: TestUnitEnum::Foo),
239+
TestUnitEnum::Bar->name => new TestEntity(str: 'UnitBar', unit_enum: TestUnitEnum::Bar),
240+
];
241+
$entity = new class($value) extends AbstractEntity {
242+
public function __construct(
243+
#[ListOf(TestEntity::class, 'unit_enum')]
244+
public array $column,
245+
) {}
246+
};
247+
$data = json_decode($entity->toArray()['column'], true);
248+
249+
$this->assertEquals('UnitFoo', $data[TestUnitEnum::Foo->name]['str']);
250+
$this->assertEquals(TestUnitEnum::Foo->name, $data[TestUnitEnum::Foo->name]['unit_enum']);
251+
$this->assertEquals('UnitBar', $data[TestUnitEnum::Bar->name]['str']);
252+
$this->assertEquals(TestUnitEnum::Bar->name, $data[TestUnitEnum::Bar->name]['unit_enum']);
253+
}
254+
255+
public function test_uncastWithBackedEnumKey(): void
256+
{
257+
$value = [
258+
TestBackedStringEnum::Foo->value => new TestEntity(str: 'BackedFoo', backed_enum: TestBackedStringEnum::Foo),
259+
TestBackedStringEnum::Bar->value => new TestEntity(str: 'BackedBar', backed_enum: TestBackedStringEnum::Bar),
260+
];
261+
$entity = new class($value) extends AbstractEntity {
262+
public function __construct(
263+
#[ListOf(TestEntity::class, 'backed_enum')]
264+
public array $column,
265+
) {}
266+
};
267+
$data = json_decode($entity->toArray()['column'], true);
268+
269+
$this->assertEquals('BackedFoo', $data[TestBackedStringEnum::Foo->value]['str']);
270+
$this->assertEquals(TestBackedStringEnum::Foo->value, $data[TestBackedStringEnum::Foo->value]['backed_enum']);
271+
$this->assertEquals('BackedBar', $data[TestBackedStringEnum::Bar->value]['str']);
272+
$this->assertEquals(TestBackedStringEnum::Bar->value, $data[TestBackedStringEnum::Bar->value]['backed_enum']);
273+
}
274+
193275
public function test_castException(): void
194276
{
195277
$entity = new class([]) extends AbstractEntity {

0 commit comments

Comments
 (0)