Skip to content

Commit c1087b6

Browse files
committed
fix(doctrine): support integer-backed enums in BackedEnumFilter
1 parent 04d5cff commit c1087b6

File tree

4 files changed

+87
-12
lines changed

4 files changed

+87
-12
lines changed

src/Doctrine/Common/Filter/BackedEnumFilterTrait.php

+19-8
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,26 @@ public function getDescription(string $resourceClass): array
5353
continue;
5454
}
5555
$propertyName = $this->normalizePropertyName($property);
56-
$description[$propertyName] = [
57-
'property' => $propertyName,
58-
'type' => 'string',
59-
'required' => false,
60-
'schema' => [
56+
$filterParameterNames = [$propertyName];
57+
$filterParameterNames[] = $propertyName.'[]';
58+
59+
foreach ($filterParameterNames as $filterParameterName) {
60+
$isCollection = str_ends_with($filterParameterName, '[]');
61+
62+
$enumValues = array_map(fn (\BackedEnum $case) => $case->value, $this->enumTypes[$property]::cases());
63+
64+
$schema = $isCollection
65+
? ['type' => 'array', 'items' => ['type' => 'string', 'enum' => $enumValues]]
66+
: ['type' => 'string', 'enum' => $enumValues];
67+
68+
$description[$filterParameterName] = [
69+
'property' => $propertyName,
6170
'type' => 'string',
62-
'enum' => array_map(fn (\BackedEnum $case) => $case->value, $this->enumTypes[$property]::cases()),
63-
],
64-
];
71+
'required' => false,
72+
'is_collection' => $isCollection,
73+
'schema' => $schema,
74+
];
75+
}
6576
}
6677

6778
return $description;

src/Doctrine/Orm/Filter/BackedEnumFilter.php

+18-4
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,14 @@ protected function filterProperty(string $property, mixed $value, QueryBuilder $
125125
return;
126126
}
127127

128-
$value = $this->normalizeValue($value, $property);
129-
if (null === $value) {
128+
$values = \is_array($value) ? $value : [$value];
129+
130+
$normalizedValues = array_filter(array_map(
131+
fn ($v) => $this->normalizeValue($v, $property),
132+
$values
133+
));
134+
135+
if (empty($normalizedValues)) {
130136
return;
131137
}
132138

@@ -139,9 +145,17 @@ protected function filterProperty(string $property, mixed $value, QueryBuilder $
139145

140146
$valueParameter = $queryNameGenerator->generateParameterName($field);
141147

148+
if (1 === \count($values)) {
149+
$queryBuilder
150+
->andWhere(\sprintf('%s.%s = :%s', $alias, $field, $valueParameter))
151+
->setParameter($valueParameter, $values[0]);
152+
153+
return;
154+
}
155+
142156
$queryBuilder
143-
->andWhere(\sprintf('%s.%s = :%s', $alias, $field, $valueParameter))
144-
->setParameter($valueParameter, $value);
157+
->andWhere(\sprintf('%s.%s IN (:%s)', $alias, $field, $valueParameter))
158+
->setParameter($valueParameter, $values);
145159
}
146160

147161
/**

src/Doctrine/Orm/Tests/Filter/BackedEnumFilterTest.php

+9
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,15 @@ public static function provideApplyTestData(): array
4343
'invalid case for nested property' => [
4444
\sprintf('SELECT o FROM %s o', Dummy::class),
4545
],
46+
'valid case (multiple values)' => [
47+
\sprintf('SELECT o FROM %s o WHERE o.dummyBackedEnum IN (:dummyBackedEnum_p1)', Dummy::class),
48+
[
49+
'dummyBackedEnum_p1' => [
50+
'one',
51+
'two',
52+
],
53+
],
54+
],
4655
]
4756
);
4857
}

src/Doctrine/Orm/Tests/Filter/BackedEnumFilterTestTrait.php

+41
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,25 @@ public function testGetDescription(): void
3232
'property' => 'dummyBackedEnum',
3333
'type' => 'string',
3434
'required' => false,
35+
'is_collection' => false,
3536
'schema' => [
3637
'type' => 'string',
3738
'enum' => ['one', 'two'],
3839
],
3940
],
41+
'dummyBackedEnum[]' => [
42+
'property' => 'dummyBackedEnum',
43+
'type' => 'string',
44+
'required' => false,
45+
'is_collection' => true,
46+
'schema' => [
47+
'type' => 'array',
48+
'items' => [
49+
'type' => 'string',
50+
'enum' => ['one', 'two'],
51+
],
52+
],
53+
],
4054
], $filter->getDescription($this->resourceClass));
4155
}
4256

@@ -49,11 +63,25 @@ public function testGetDescriptionDefaultFields(): void
4963
'property' => 'dummyBackedEnum',
5064
'type' => 'string',
5165
'required' => false,
66+
'is_collection' => false,
5267
'schema' => [
5368
'type' => 'string',
5469
'enum' => ['one', 'two'],
5570
],
5671
],
72+
'dummyBackedEnum[]' => [
73+
'property' => 'dummyBackedEnum',
74+
'type' => 'string',
75+
'required' => false,
76+
'is_collection' => true,
77+
'schema' => [
78+
'type' => 'array',
79+
'items' => [
80+
'type' => 'string',
81+
'enum' => ['one', 'two'],
82+
],
83+
],
84+
],
5785
], $filter->getDescription($this->resourceClass));
5886
}
5987

@@ -100,6 +128,19 @@ private static function provideApplyTestArguments(): array
100128
'relatedDummy.dummyBackedEnum' => 'foo',
101129
],
102130
],
131+
'valid case (multiple values)' => [
132+
[
133+
'id' => null,
134+
'name' => null,
135+
'dummyBackedEnum' => null,
136+
],
137+
[
138+
'dummyBackedEnum' => [
139+
'one',
140+
'two',
141+
],
142+
],
143+
],
103144
];
104145
}
105146
}

0 commit comments

Comments
 (0)