Skip to content

Commit 781dce7

Browse files
authored
Merge pull request #4111 from alanpoulain/merge-2.6
Merge 2.6
2 parents 6f88fb4 + 0428a86 commit 781dce7

File tree

12 files changed

+123
-77
lines changed

12 files changed

+123
-77
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ jobs:
113113
with:
114114
php-version: ${{ matrix.php }}
115115
tools: pecl, composer
116-
extensions: intl, bcmath, curl, openssl, mbstring
116+
extensions: intl, bcmath, curl, openssl, mbstring, pdo_sqlite
117117
coverage: pcov
118118
ini-values: memory_limit=-1
119119
- name: Get composer cache directory
@@ -507,7 +507,7 @@ jobs:
507507
with:
508508
php-version: ${{ matrix.php }}
509509
tools: pecl, composer
510-
extensions: intl, bcmath, curl, openssl, mbstring
510+
extensions: intl, bcmath, curl, openssl, mbstring, mongodb
511511
coverage: none
512512
ini-values: memory_limit=-1
513513
- name: Get composer cache directory
@@ -669,7 +669,7 @@ jobs:
669669
- name: Update project dependencies
670670
run: composer update --no-interaction --no-progress --ansi
671671
- name: Require Symfony Uid
672-
run: composer require symfony/uid --dev --no-interaction --no-progress --ansi
672+
run: composer require symfony/uid symfony/intl --dev --no-interaction --no-progress --ansi
673673
- name: Flag held back Symfony packages
674674
env:
675675
symfony_version: ${{ matrix.symfony }}

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,15 @@
1818
* Mercure: Do not use data in options when deleting (#4056)
1919
* Doctrine: Support for foreign identifiers (#4042)
2020
* Doctrine: Support for binary UUID in search filter (#3774)
21+
* Doctrine: Do not add join or lookup for search filter with empty value (#3703)
22+
* Doctrine: Reduce code duplication in search filter (#3541)
2123
* JSON Schema: Allow generating documentation when property and method start from "is" (property `isActive` and method `isActive`) (#4064)
2224
* OpenAPI: Fix missing 422 responses in the documentation (#4086)
2325
* OpenAPI: Fix error when schema is empty (#4051)
2426
* OpenAPI: Do not set scheme to oauth2 when generating securitySchemes (#4073)
2527
* OpenAPI: Fix missing `$ref` when no `type` is used in context (#4076)
2628
* GraphQL: Fix "Resource class cannot be determined." error when a null iterable field is returned (#4092)
29+
* Metadata: Check the output class when calculating serializer groups (#3696)
2730

2831
## 2.6.2
2932

src/Bridge/Doctrine/MongoDbOdm/Filter/SearchFilter.php

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -77,22 +77,27 @@ protected function filterProperty(string $property, $value, Builder $aggregation
7777

7878
$matchField = $field = $property;
7979

80+
$values = $this->normalizeValues((array) $value, $property);
81+
if (null === $values) {
82+
return;
83+
}
84+
8085
$associations = [];
8186
if ($this->isPropertyNested($property, $resourceClass)) {
8287
[$matchField, $field, $associations] = $this->addLookupsForNestedProperty($property, $aggregationBuilder, $resourceClass);
8388
}
8489

85-
/**
86-
* @var MongoDBClassMetadata
87-
*/
88-
$metadata = $this->getNestedMetadata($resourceClass, $associations);
90+
$caseSensitive = true;
91+
$strategy = $this->properties[$property] ?? self::STRATEGY_EXACT;
8992

90-
$values = $this->normalizeValues((array) $value, $property);
91-
if (null === $values) {
92-
return;
93+
// prefixing the strategy with i makes it case insensitive
94+
if (0 === strpos($strategy, 'i')) {
95+
$strategy = substr($strategy, 1);
96+
$caseSensitive = false;
9397
}
9498

95-
$caseSensitive = true;
99+
/** @var MongoDBClassMetadata */
100+
$metadata = $this->getNestedMetadata($resourceClass, $associations);
96101

97102
if ($metadata->hasField($field) && !$metadata->hasAssociation($field)) {
98103
if ('id' === $field) {
@@ -107,23 +112,9 @@ protected function filterProperty(string $property, $value, Builder $aggregation
107112
return;
108113
}
109114

110-
$strategy = $this->properties[$property] ?? self::STRATEGY_EXACT;
111-
112-
// prefixing the strategy with i makes it case insensitive
113-
if (0 === strpos($strategy, 'i')) {
114-
$strategy = substr($strategy, 1);
115-
$caseSensitive = false;
116-
}
115+
$this->addEqualityMatchStrategy($strategy, $aggregationBuilder, $field, $matchField, $values, $caseSensitive, $metadata);
117116

118-
$inValues = [];
119-
foreach ($values as $inValue) {
120-
$inValues[] = $this->addEqualityMatchStrategy($strategy, $field, $inValue, $caseSensitive, $metadata);
121-
}
122-
123-
$aggregationBuilder
124-
->match()
125-
->field($matchField)
126-
->in($inValues);
117+
return;
127118
}
128119

129120
// metadata doesn't have the field, nor an association on the field
@@ -132,7 +123,6 @@ protected function filterProperty(string $property, $value, Builder $aggregation
132123
}
133124

134125
$values = array_map([$this, 'getIdFromValue'], $values);
135-
$associationFieldIdentifier = 'id';
136126
$doctrineTypeField = $this->getDoctrineFieldType($property, $resourceClass);
137127

138128
if (null !== $this->identifiersExtractor) {
@@ -149,23 +139,39 @@ protected function filterProperty(string $property, $value, Builder $aggregation
149139
return;
150140
}
151141

142+
$this->addEqualityMatchStrategy($strategy, $aggregationBuilder, $field, $matchField, $values, $caseSensitive, $metadata);
143+
}
144+
145+
/**
146+
* Add equality match stage according to the strategy.
147+
*/
148+
private function addEqualityMatchStrategy(string $strategy, Builder $aggregationBuilder, string $field, string $matchField, $values, bool $caseSensitive, ClassMetadata $metadata): void
149+
{
150+
$inValues = [];
151+
foreach ($values as $inValue) {
152+
$inValues[] = $this->getEqualityMatchStrategyValue($strategy, $field, $inValue, $caseSensitive, $metadata);
153+
}
154+
152155
$aggregationBuilder
153156
->match()
154157
->field($matchField)
155-
->in($values);
158+
->in($inValues);
156159
}
157160

158161
/**
159-
* Add equality match stage according to the strategy.
162+
* Get equality match value according to the strategy.
160163
*
161164
* @throws InvalidArgumentException If strategy does not exist
162165
*
163166
* @return Regex|string
164167
*/
165-
private function addEqualityMatchStrategy(string $strategy, string $field, $value, bool $caseSensitive, ClassMetadata $metadata)
168+
private function getEqualityMatchStrategyValue(string $strategy, string $field, $value, bool $caseSensitive, ClassMetadata $metadata)
166169
{
167170
$type = $metadata->getTypeOfField($field);
168171

172+
if (!MongoDbType::hasType($type)) {
173+
return $value;
174+
}
169175
if (MongoDbType::STRING !== $type) {
170176
return MongoDbType::getType($type)->convertToDatabaseValue($value);
171177
}

src/Bridge/Doctrine/Orm/Filter/SearchFilter.php

Lines changed: 13 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -81,14 +81,23 @@ protected function filterProperty(string $property, $value, QueryBuilder $queryB
8181
$alias = $queryBuilder->getRootAliases()[0];
8282
$field = $property;
8383

84+
$values = $this->normalizeValues((array) $value, $property);
85+
if (null === $values) {
86+
return;
87+
}
88+
8489
$associations = [];
8590
if ($this->isPropertyNested($property, $resourceClass)) {
8691
[$alias, $field, $associations] = $this->addJoinsForNestedProperty($property, $alias, $queryBuilder, $queryNameGenerator, $resourceClass);
8792
}
8893

89-
$values = $this->normalizeValues((array) $value, $property);
90-
if (null === $values) {
91-
return;
94+
$caseSensitive = true;
95+
$strategy = $this->properties[$property] ?? self::STRATEGY_EXACT;
96+
97+
// prefixing the strategy with i makes it case insensitive
98+
if (0 === strpos($strategy, 'i')) {
99+
$strategy = substr($strategy, 1);
100+
$caseSensitive = false;
92101
}
93102

94103
$metadata = $this->getNestedMetadata($resourceClass, $associations);
@@ -106,15 +115,6 @@ protected function filterProperty(string $property, $value, QueryBuilder $queryB
106115
return;
107116
}
108117

109-
$caseSensitive = true;
110-
$strategy = $this->properties[$property] ?? self::STRATEGY_EXACT;
111-
112-
// prefixing the strategy with i makes it case insensitive
113-
if (0 === strpos($strategy, 'i')) {
114-
$strategy = substr($strategy, 1);
115-
$caseSensitive = false;
116-
}
117-
118118
$this->addWhereByStrategy($strategy, $queryBuilder, $queryNameGenerator, $alias, $field, $values, $caseSensitive, $metadata);
119119

120120
return;
@@ -145,34 +145,12 @@ protected function filterProperty(string $property, $value, QueryBuilder $queryB
145145

146146
$associationAlias = $alias;
147147
$associationField = $field;
148-
$valueParameter = $queryNameGenerator->generateParameterName($associationField);
149148
if ($metadata->isCollectionValuedAssociation($associationField)) {
150149
$associationAlias = QueryBuilderHelper::addJoinOnce($queryBuilder, $queryNameGenerator, $alias, $associationField);
151150
$associationField = $associationFieldIdentifier;
152151
}
153152

154-
$type = $metadata->getTypeOfField($associationField);
155-
156-
if (1 === \count($values)) {
157-
$queryBuilder
158-
->andWhere($queryBuilder->expr()->eq($associationAlias.'.'.$associationField, ':'.$valueParameter))
159-
->setParameter($valueParameter, $values[0], $type);
160-
161-
return;
162-
}
163-
164-
$parameters = $queryBuilder->getParameters();
165-
$inQuery = [];
166-
167-
foreach ($values as $val) {
168-
$inQuery[] = ':'.$valueParameter;
169-
$parameters->add(new Parameter($valueParameter, $val, $type));
170-
$valueParameter = $queryNameGenerator->generateParameterName($associationField);
171-
}
172-
173-
$queryBuilder
174-
->andWhere($associationAlias.'.'.$associationField.' IN ('.implode(', ', $inQuery).')')
175-
->setParameters($parameters);
153+
$this->addWhereByStrategy($strategy, $queryBuilder, $queryNameGenerator, $associationAlias, $associationField, $values, $caseSensitive, $metadata);
176154
}
177155

178156
/**

src/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,11 @@ private function getSerializerAttributeMetadata(string $class, string $attribute
209209
*/
210210
private function getClassSerializerGroups(string $class): array
211211
{
212+
$resourceMetadata = $this->resourceMetadataFactory->create($class);
213+
if ($outputClass = $resourceMetadata->getAttribute('output')['class'] ?? null) {
214+
$class = $outputClass;
215+
}
216+
212217
$serializerClassMetadata = $this->serializerClassMetadataFactory->getMetadataFor($class);
213218

214219
$groups = [];

src/OpenApi/Model/PathItem.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -138,31 +138,31 @@ public function withDescription(string $description): self
138138
return $clone;
139139
}
140140

141-
public function withGet(Operation $get): self
141+
public function withGet(?Operation $get): self
142142
{
143143
$clone = clone $this;
144144
$clone->get = $get;
145145

146146
return $clone;
147147
}
148148

149-
public function withPut(Operation $put): self
149+
public function withPut(?Operation $put): self
150150
{
151151
$clone = clone $this;
152152
$clone->put = $put;
153153

154154
return $clone;
155155
}
156156

157-
public function withPost(Operation $post): self
157+
public function withPost(?Operation $post): self
158158
{
159159
$clone = clone $this;
160160
$clone->post = $post;
161161

162162
return $clone;
163163
}
164164

165-
public function withDelete(Operation $delete): self
165+
public function withDelete(?Operation $delete): self
166166
{
167167
$clone = clone $this;
168168
$clone->delete = $delete;
@@ -186,7 +186,7 @@ public function withHead(Operation $head): self
186186
return $clone;
187187
}
188188

189-
public function withPatch(Operation $patch): self
189+
public function withPatch(?Operation $patch): self
190190
{
191191
$clone = clone $this;
192192
$clone->patch = $patch;

src/OpenApi/OpenApi.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public function getServers(): array
6161
return $this->servers;
6262
}
6363

64-
public function getPaths()
64+
public function getPaths(): Paths
6565
{
6666
return $this->paths;
6767
}

tests/Bridge/Doctrine/Common/Filter/SearchFilterTestTrait.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,14 @@ private function provideApplyTestArguments(): array
466466
'relatedDummy.symfony' => 'exact',
467467
],
468468
],
469+
'empty nested property' => [
470+
[
471+
'relatedDummy.symfony' => null,
472+
],
473+
[
474+
'relatedDummy.symfony' => [],
475+
],
476+
],
469477
];
470478
}
471479
}

tests/Bridge/Doctrine/MongoDbOdm/Filter/SearchFilterTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,10 @@ public function provideApplyTestData(): array
686686
],
687687
$filterFactory,
688688
],
689+
'empty nested property' => [
690+
[],
691+
$filterFactory,
692+
],
689693
]
690694
);
691695
}

tests/Bridge/Doctrine/Orm/Filter/SearchFilterTest.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -543,11 +543,11 @@ public function provideApplyTestData(): array
543543
$filterFactory,
544544
],
545545
'mixed IRI and entity ID values for relations' => [
546-
sprintf('SELECT %s FROM %s %1$s INNER JOIN %1$s.relatedDummies relatedDummies_a1 WHERE %1$s.relatedDummy IN (:relatedDummy_p1, :relatedDummy_p2) AND relatedDummies_a1.id = :relatedDummies_p4', $this->alias, Dummy::class),
546+
sprintf('SELECT %s FROM %s %1$s INNER JOIN %1$s.relatedDummies relatedDummies_a1 WHERE %1$s.relatedDummy IN (:relatedDummy_p1, :relatedDummy_p2) AND relatedDummies_a1.id = :id_p4', $this->alias, Dummy::class),
547547
[
548548
'relatedDummy_p1' => 1,
549549
'relatedDummy_p2' => 2,
550-
'relatedDummies_p4' => 1,
550+
'id_p4' => 1,
551551
],
552552
$filterFactory,
553553
],
@@ -559,6 +559,11 @@ public function provideApplyTestData(): array
559559
],
560560
$filterFactory,
561561
],
562+
'empty nested property' => [
563+
sprintf('SELECT %s FROM %s %1$s', $this->alias, Dummy::class),
564+
[],
565+
$filterFactory,
566+
],
562567
]
563568
);
564569
}

0 commit comments

Comments
 (0)