From 7c6f96f4af9e787c6eafcbd145cd31a4533f6340 Mon Sep 17 00:00:00 2001 From: Wybren Koelmans Date: Mon, 1 Mar 2021 18:19:43 +0100 Subject: [PATCH 1/8] Do not add JOINs for Filters without a value (#3703) --- CHANGELOG.md | 1 + src/Bridge/Doctrine/MongoDbOdm/Filter/SearchFilter.php | 10 +++++----- src/Bridge/Doctrine/Orm/Filter/SearchFilter.php | 10 +++++----- .../Doctrine/Common/Filter/SearchFilterTestTrait.php | 8 ++++++++ .../Doctrine/MongoDbOdm/Filter/SearchFilterTest.php | 4 ++++ tests/Bridge/Doctrine/Orm/Filter/SearchFilterTest.php | 5 +++++ 6 files changed, 28 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cdaebd63f18..2000f7e915e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ * Mercure: Do not use data in options when deleting (#4056) * Doctrine: Support for foreign identifiers (#4042) * Doctrine: Support for binary UUID in search filter (#3774) +* Doctrine: Do not add join or lookup for search filter with empty value (#3703) * JSON Schema: Allow generating documentation when property and method start from "is" (property `isActive` and method `isActive`) (#4064) * OpenAPI: Fix missing 422 responses in the documentation (#4086) * OpenAPI: Fix error when schema is empty (#4051) diff --git a/src/Bridge/Doctrine/MongoDbOdm/Filter/SearchFilter.php b/src/Bridge/Doctrine/MongoDbOdm/Filter/SearchFilter.php index 91cb23dc3cf..153dae64fa4 100644 --- a/src/Bridge/Doctrine/MongoDbOdm/Filter/SearchFilter.php +++ b/src/Bridge/Doctrine/MongoDbOdm/Filter/SearchFilter.php @@ -77,6 +77,11 @@ protected function filterProperty(string $property, $value, Builder $aggregation $matchField = $field = $property; + $values = $this->normalizeValues((array) $value, $property); + if (null === $values) { + return; + } + $associations = []; if ($this->isPropertyNested($property, $resourceClass)) { [$matchField, $field, $associations] = $this->addLookupsForNestedProperty($property, $aggregationBuilder, $resourceClass); @@ -87,11 +92,6 @@ protected function filterProperty(string $property, $value, Builder $aggregation */ $metadata = $this->getNestedMetadata($resourceClass, $associations); - $values = $this->normalizeValues((array) $value, $property); - if (null === $values) { - return; - } - $caseSensitive = true; if ($metadata->hasField($field) && !$metadata->hasAssociation($field)) { diff --git a/src/Bridge/Doctrine/Orm/Filter/SearchFilter.php b/src/Bridge/Doctrine/Orm/Filter/SearchFilter.php index ad26c178b54..0fda7e6470d 100644 --- a/src/Bridge/Doctrine/Orm/Filter/SearchFilter.php +++ b/src/Bridge/Doctrine/Orm/Filter/SearchFilter.php @@ -81,16 +81,16 @@ protected function filterProperty(string $property, $value, QueryBuilder $queryB $alias = $queryBuilder->getRootAliases()[0]; $field = $property; - $associations = []; - if ($this->isPropertyNested($property, $resourceClass)) { - [$alias, $field, $associations] = $this->addJoinsForNestedProperty($property, $alias, $queryBuilder, $queryNameGenerator, $resourceClass); - } - $values = $this->normalizeValues((array) $value, $property); if (null === $values) { return; } + $associations = []; + if ($this->isPropertyNested($property, $resourceClass)) { + [$alias, $field, $associations] = $this->addJoinsForNestedProperty($property, $alias, $queryBuilder, $queryNameGenerator, $resourceClass); + } + $metadata = $this->getNestedMetadata($resourceClass, $associations); if ($metadata->hasField($field)) { diff --git a/tests/Bridge/Doctrine/Common/Filter/SearchFilterTestTrait.php b/tests/Bridge/Doctrine/Common/Filter/SearchFilterTestTrait.php index 5062ed163a8..6916e3b9645 100644 --- a/tests/Bridge/Doctrine/Common/Filter/SearchFilterTestTrait.php +++ b/tests/Bridge/Doctrine/Common/Filter/SearchFilterTestTrait.php @@ -466,6 +466,14 @@ private function provideApplyTestArguments(): array 'relatedDummy.symfony' => 'exact', ], ], + 'empty nested property' => [ + [ + 'relatedDummy.symfony' => null, + ], + [ + 'relatedDummy.symfony' => [], + ], + ], ]; } } diff --git a/tests/Bridge/Doctrine/MongoDbOdm/Filter/SearchFilterTest.php b/tests/Bridge/Doctrine/MongoDbOdm/Filter/SearchFilterTest.php index b090f818409..a378e6e7d69 100644 --- a/tests/Bridge/Doctrine/MongoDbOdm/Filter/SearchFilterTest.php +++ b/tests/Bridge/Doctrine/MongoDbOdm/Filter/SearchFilterTest.php @@ -686,6 +686,10 @@ public function provideApplyTestData(): array ], $filterFactory, ], + 'empty nested property' => [ + [], + $filterFactory, + ], ] ); } diff --git a/tests/Bridge/Doctrine/Orm/Filter/SearchFilterTest.php b/tests/Bridge/Doctrine/Orm/Filter/SearchFilterTest.php index c202e3c5475..8add7097424 100644 --- a/tests/Bridge/Doctrine/Orm/Filter/SearchFilterTest.php +++ b/tests/Bridge/Doctrine/Orm/Filter/SearchFilterTest.php @@ -559,6 +559,11 @@ public function provideApplyTestData(): array ], $filterFactory, ], + 'empty nested property' => [ + sprintf('SELECT %s FROM %s %1$s', $this->alias, Dummy::class), + [], + $filterFactory, + ], ] ); } From 3e742ff85fd55b8caecbfde141822973f938a403 Mon Sep 17 00:00:00 2001 From: Damian Date: Thu, 25 Feb 2021 18:11:27 +0100 Subject: [PATCH 2/8] Allow unset PathItem method After disabling itemOperation `GET` ``` itemOperations: [ 'get' => [ 'controller' => ApiPlatform\Core\Action\NotFoundAction::class, 'read' => false, 'output' => false, ], ] ``` there is not nice way to remove that path from OpenApi docs. Now to do that you have to write: ``` $pathItem = $openApi->getPaths()->getPath('/resource/{id}'); $openApi->getPaths()->addPath( '/resource/{id}', new Model\PathItem( $pathItem->getRef(), $pathItem->getSummary(), $pathItem->getDescription(), null, $pathItem->getPut(), $pathItem->getPost(), $pathItem->getDelete(), $pathItem->getOptions(), $pathItem->getHead(), $pathItem->getPatch(), $pathItem->getTrace(), $pathItem->getServers(), $pathItem->getParameters(), ) ); ``` After change it will be: ``` $pathItem = $openApi->getPaths()->getPath('/resource/{id}'); $openApi->getPaths()->addPath( '/resource/{id}', $pathItem->withGet(null) ); ``` --- src/OpenApi/Model/PathItem.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/OpenApi/Model/PathItem.php b/src/OpenApi/Model/PathItem.php index 5c07c9006c2..fae2c59a0ff 100644 --- a/src/OpenApi/Model/PathItem.php +++ b/src/OpenApi/Model/PathItem.php @@ -138,7 +138,7 @@ public function withDescription(string $description): self return $clone; } - public function withGet(Operation $get): self + public function withGet(?Operation $get): self { $clone = clone $this; $clone->get = $get; @@ -146,7 +146,7 @@ public function withGet(Operation $get): self return $clone; } - public function withPut(Operation $put): self + public function withPut(?Operation $put): self { $clone = clone $this; $clone->put = $put; @@ -154,7 +154,7 @@ public function withPut(Operation $put): self return $clone; } - public function withPost(Operation $post): self + public function withPost(?Operation $post): self { $clone = clone $this; $clone->post = $post; @@ -162,7 +162,7 @@ public function withPost(Operation $post): self return $clone; } - public function withDelete(Operation $delete): self + public function withDelete(?Operation $delete): self { $clone = clone $this; $clone->delete = $delete; @@ -186,7 +186,7 @@ public function withHead(Operation $head): self return $clone; } - public function withPatch(Operation $patch): self + public function withPatch(?Operation $patch): self { $clone = clone $this; $clone->patch = $patch; From c25f9619984889fc0503e773d7b4d0b58a6d84c9 Mon Sep 17 00:00:00 2001 From: soyuka Date: Tue, 2 Mar 2021 09:15:17 +0100 Subject: [PATCH 3/8] OpenAPI PathItem Add test nullable operation --- tests/OpenApi/Factory/OpenApiFactoryTest.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/OpenApi/Factory/OpenApiFactoryTest.php b/tests/OpenApi/Factory/OpenApiFactoryTest.php index 42e74f73e05..bd2ea6aed0c 100644 --- a/tests/OpenApi/Factory/OpenApiFactoryTest.php +++ b/tests/OpenApi/Factory/OpenApiFactoryTest.php @@ -30,6 +30,7 @@ use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Core\OpenApi\Factory\OpenApiFactory; use ApiPlatform\Core\OpenApi\Model; +use ApiPlatform\Core\OpenApi\Model\PathItem; use ApiPlatform\Core\OpenApi\OpenApi; use ApiPlatform\Core\OpenApi\Options; use ApiPlatform\Core\OpenApi\Serializer\OpenApiNormalizer; @@ -745,4 +746,20 @@ public function testSubresourceDocumentation() $normalizer = new OpenApiNormalizer($normalizers[0]); $normalizer->normalize($openApi); } + + public function testResetPathItem() + { + $pathItem = new PathItem(); + $pathItem->withGet(null); + $pathItem->withDelete(null); + $pathItem->withPost(null); + $pathItem->withPut(null); + $pathItem->withPatch(null); + + $this->assertNull($pathItem->getGet()); + $this->assertNull($pathItem->getDelete()); + $this->assertNull($pathItem->getPost()); + $this->assertNull($pathItem->getPut()); + $this->assertNull($pathItem->getPatch()); + } } From e270b03a6a0ca1a0f444f4b8c94dca87e1ec9409 Mon Sep 17 00:00:00 2001 From: soyuka Date: Tue, 2 Mar 2021 09:22:35 +0100 Subject: [PATCH 4/8] Fix tests --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3d6fa355767..0f44c0926ce 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -670,7 +670,7 @@ jobs: - name: Update project dependencies run: composer update --no-interaction --no-progress --ansi - name: Require Symfony Uid - run: composer require symfony/uid --dev --no-interaction --no-progress --ansi + run: composer require symfony/uid symfony/intl --dev --no-interaction --no-progress --ansi - name: Flag held back Symfony packages env: symfony_version: ${{ matrix.symfony }} From ee275d25a63bc47cdf9d9a5f08275b9667cd6140 Mon Sep 17 00:00:00 2001 From: Antoine Bluchet Date: Tue, 2 Mar 2021 11:22:23 +0100 Subject: [PATCH 5/8] Update OpenApi.php (#4108) Hello, i just add the return type for method `getPaths` Co-authored-by: Abdouni Abdelkarim --- src/OpenApi/OpenApi.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OpenApi/OpenApi.php b/src/OpenApi/OpenApi.php index 317d5bd7a98..a4289f08941 100644 --- a/src/OpenApi/OpenApi.php +++ b/src/OpenApi/OpenApi.php @@ -61,7 +61,7 @@ public function getServers(): array return $this->servers; } - public function getPaths() + public function getPaths(): Paths { return $this->paths; } From cecd948a133fa5ff773eddf4e8fe5c61c4fd1455 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Tue, 2 Mar 2021 05:36:17 -0500 Subject: [PATCH 6/8] Checking the output option when calculating property metadata (#3696) --- CHANGELOG.md | 1 + .../SerializerPropertyMetadataFactory.php | 5 ++++ .../SerializerPropertyMetadataFactoryTest.php | 26 ++++++++++++++++--- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2000f7e915e..4beea5d57b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ * OpenAPI: Do not set scheme to oauth2 when generating securitySchemes (#4073) * OpenAPI: Fix missing `$ref` when no `type` is used in context (#4076) * GraphQL: Fix "Resource class cannot be determined." error when a null iterable field is returned (#4092) +* Metadata: Check the output class when calculating serializer groups (#3696) ## 2.6.2 diff --git a/src/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php b/src/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php index 5df7fdb3420..1078d3af945 100644 --- a/src/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php +++ b/src/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php @@ -209,6 +209,11 @@ private function getSerializerAttributeMetadata(string $class, string $attribute */ private function getClassSerializerGroups(string $class): array { + $resourceMetadata = $this->resourceMetadataFactory->create($class); + if ($outputClass = $resourceMetadata->getAttribute('output')['class'] ?? null) { + $class = $outputClass; + } + $serializerClassMetadata = $this->serializerClassMetadataFactory->getMetadataFor($class); $groups = []; diff --git a/tests/Metadata/Property/Factory/SerializerPropertyMetadataFactoryTest.php b/tests/Metadata/Property/Factory/SerializerPropertyMetadataFactoryTest.php index f068623bef3..5ed15722d24 100644 --- a/tests/Metadata/Property/Factory/SerializerPropertyMetadataFactoryTest.php +++ b/tests/Metadata/Property/Factory/SerializerPropertyMetadataFactoryTest.php @@ -21,6 +21,7 @@ use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\DummyIgnoreProperty; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\DummyCar; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\DummyTableInheritance; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\DummyTableInheritanceChild; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\RelatedDummy; @@ -56,7 +57,7 @@ public function testConstruct() /** * @dataProvider groupsProvider */ - public function testCreate($readGroups, $writeGroups) + public function testCreate($readGroups, $writeGroups, ?string $relatedOutputClass = null) { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $dummyResourceMetadata = (new ResourceMetadata()) @@ -69,6 +70,13 @@ public function testCreate($readGroups, $writeGroups) ], ]); $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyResourceMetadata); + $relatedDummyResourceMetadata = new ResourceMetadata(); + if ($relatedOutputClass) { + $relatedDummyResourceMetadata = $relatedDummyResourceMetadata->withAttributes([ + 'output' => ['class' => $relatedOutputClass], + ]); + } + $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn($relatedDummyResourceMetadata); $serializerClassMetadataFactoryProphecy = $this->prophesize(SerializerClassMetadataFactoryInterface::class); $dummySerializerClassMetadata = new SerializerClassMetadata(Dummy::class); @@ -88,6 +96,12 @@ public function testCreate($readGroups, $writeGroups) $nameSerializerAttributeMetadata->addGroup('dummy_read'); $relatedDummySerializerClassMetadata->addAttributeMetadata($nameSerializerAttributeMetadata); $serializerClassMetadataFactoryProphecy->getMetadataFor(RelatedDummy::class)->willReturn($relatedDummySerializerClassMetadata); + $dummyCarSerializerClassMetadata = new SerializerClassMetadata(DummyCar::class); + $nameSerializerAttributeMetadata = new SerializerAttributeMetadata('name'); + $nameSerializerAttributeMetadata->addGroup('dummy_car_read'); + $nameSerializerAttributeMetadata->addGroup('dummy_write'); + $dummyCarSerializerClassMetadata->addAttributeMetadata($nameSerializerAttributeMetadata); + $serializerClassMetadataFactoryProphecy->getMetadataFor(DummyCar::class)->willReturn($dummyCarSerializerClassMetadata); $decoratedProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); $fooPropertyMetadata = (new PropertyMetadata()) @@ -120,8 +134,13 @@ public function testCreate($readGroups, $writeGroups) $this->assertInstanceOf(PropertyMetadata::class, $actual[1]); $this->assertTrue($actual[1]->isReadable()); $this->assertTrue($actual[1]->isWritable()); - $this->assertTrue($actual[1]->isReadableLink()); - $this->assertFalse($actual[1]->isWritableLink()); + if ($relatedOutputClass) { + $this->assertFalse($actual[1]->isReadableLink()); + $this->assertTrue($actual[1]->isWritableLink()); + } else { + $this->assertTrue($actual[1]->isReadableLink()); + $this->assertFalse($actual[1]->isWritableLink()); + } $this->assertInstanceOf(PropertyMetadata::class, $actual[2]); $this->assertFalse($actual[2]->isReadable()); @@ -133,6 +152,7 @@ public function groupsProvider(): array return [ [['dummy_read'], ['dummy_write']], ['dummy_read', 'dummy_write'], + ['dummy_read', 'dummy_write', DummyCar::class], ]; } From 9df5a5e3fe438cd265c20bd330f82bce8ef6e709 Mon Sep 17 00:00:00 2001 From: Julien PIERRONT Date: Wed, 3 Mar 2021 12:01:45 +0100 Subject: [PATCH 7/8] SearchFilter: Refactor code to reduce code duplication and makes it easier to add new strategies to classes inheriting from SearchFilter class (#3541) --- CHANGELOG.md | 1 + .../MongoDbOdm/Filter/SearchFilter.php | 56 ++++++++++--------- .../Doctrine/Orm/Filter/SearchFilter.php | 42 ++++---------- .../Doctrine/Orm/Filter/SearchFilterTest.php | 4 +- 4 files changed, 44 insertions(+), 59 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4beea5d57b3..cbdb5a0e951 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ * Doctrine: Support for foreign identifiers (#4042) * Doctrine: Support for binary UUID in search filter (#3774) * Doctrine: Do not add join or lookup for search filter with empty value (#3703) +* Doctrine: Reduce code duplication in search filter (#3541) * JSON Schema: Allow generating documentation when property and method start from "is" (property `isActive` and method `isActive`) (#4064) * OpenAPI: Fix missing 422 responses in the documentation (#4086) * OpenAPI: Fix error when schema is empty (#4051) diff --git a/src/Bridge/Doctrine/MongoDbOdm/Filter/SearchFilter.php b/src/Bridge/Doctrine/MongoDbOdm/Filter/SearchFilter.php index 153dae64fa4..e14f74888ff 100644 --- a/src/Bridge/Doctrine/MongoDbOdm/Filter/SearchFilter.php +++ b/src/Bridge/Doctrine/MongoDbOdm/Filter/SearchFilter.php @@ -87,12 +87,17 @@ protected function filterProperty(string $property, $value, Builder $aggregation [$matchField, $field, $associations] = $this->addLookupsForNestedProperty($property, $aggregationBuilder, $resourceClass); } - /** - * @var MongoDBClassMetadata - */ - $metadata = $this->getNestedMetadata($resourceClass, $associations); - $caseSensitive = true; + $strategy = $this->properties[$property] ?? self::STRATEGY_EXACT; + + // prefixing the strategy with i makes it case insensitive + if (0 === strpos($strategy, 'i')) { + $strategy = substr($strategy, 1); + $caseSensitive = false; + } + + /** @var MongoDBClassMetadata */ + $metadata = $this->getNestedMetadata($resourceClass, $associations); if ($metadata->hasField($field) && !$metadata->hasAssociation($field)) { if ('id' === $field) { @@ -107,23 +112,9 @@ protected function filterProperty(string $property, $value, Builder $aggregation return; } - $strategy = $this->properties[$property] ?? self::STRATEGY_EXACT; + $this->addEqualityMatchStrategy($strategy, $aggregationBuilder, $field, $matchField, $values, $caseSensitive, $metadata); - // prefixing the strategy with i makes it case insensitive - if (0 === strpos($strategy, 'i')) { - $strategy = substr($strategy, 1); - $caseSensitive = false; - } - - $inValues = []; - foreach ($values as $inValue) { - $inValues[] = $this->addEqualityMatchStrategy($strategy, $field, $inValue, $caseSensitive, $metadata); - } - - $aggregationBuilder - ->match() - ->field($matchField) - ->in($inValues); + return; } // metadata doesn't have the field, nor an association on the field @@ -132,7 +123,6 @@ protected function filterProperty(string $property, $value, Builder $aggregation } $values = array_map([$this, 'getIdFromValue'], $values); - $associationFieldIdentifier = 'id'; $doctrineTypeField = $this->getDoctrineFieldType($property, $resourceClass); if (null !== $this->identifiersExtractor) { @@ -149,23 +139,39 @@ protected function filterProperty(string $property, $value, Builder $aggregation return; } + $this->addEqualityMatchStrategy($strategy, $aggregationBuilder, $field, $matchField, $values, $caseSensitive, $metadata); + } + + /** + * Add equality match stage according to the strategy. + */ + private function addEqualityMatchStrategy(string $strategy, Builder $aggregationBuilder, string $field, string $matchField, $values, bool $caseSensitive, ClassMetadata $metadata): void + { + $inValues = []; + foreach ($values as $inValue) { + $inValues[] = $this->getEqualityMatchStrategyValue($strategy, $field, $inValue, $caseSensitive, $metadata); + } + $aggregationBuilder ->match() ->field($matchField) - ->in($values); + ->in($inValues); } /** - * Add equality match stage according to the strategy. + * Get equality match value according to the strategy. * * @throws InvalidArgumentException If strategy does not exist * * @return Regex|string */ - private function addEqualityMatchStrategy(string $strategy, string $field, $value, bool $caseSensitive, ClassMetadata $metadata) + private function getEqualityMatchStrategyValue(string $strategy, string $field, $value, bool $caseSensitive, ClassMetadata $metadata) { $type = $metadata->getTypeOfField($field); + if (!MongoDbType::hasType($type)) { + return $value; + } if (MongoDbType::STRING !== $type) { return MongoDbType::getType($type)->convertToDatabaseValue($value); } diff --git a/src/Bridge/Doctrine/Orm/Filter/SearchFilter.php b/src/Bridge/Doctrine/Orm/Filter/SearchFilter.php index 0fda7e6470d..858406d421e 100644 --- a/src/Bridge/Doctrine/Orm/Filter/SearchFilter.php +++ b/src/Bridge/Doctrine/Orm/Filter/SearchFilter.php @@ -91,6 +91,15 @@ protected function filterProperty(string $property, $value, QueryBuilder $queryB [$alias, $field, $associations] = $this->addJoinsForNestedProperty($property, $alias, $queryBuilder, $queryNameGenerator, $resourceClass); } + $caseSensitive = true; + $strategy = $this->properties[$property] ?? self::STRATEGY_EXACT; + + // prefixing the strategy with i makes it case insensitive + if (0 === strpos($strategy, 'i')) { + $strategy = substr($strategy, 1); + $caseSensitive = false; + } + $metadata = $this->getNestedMetadata($resourceClass, $associations); if ($metadata->hasField($field)) { @@ -106,15 +115,6 @@ protected function filterProperty(string $property, $value, QueryBuilder $queryB return; } - $caseSensitive = true; - $strategy = $this->properties[$property] ?? self::STRATEGY_EXACT; - - // prefixing the strategy with i makes it case insensitive - if (0 === strpos($strategy, 'i')) { - $strategy = substr($strategy, 1); - $caseSensitive = false; - } - $this->addWhereByStrategy($strategy, $queryBuilder, $queryNameGenerator, $alias, $field, $values, $caseSensitive, $metadata); return; @@ -145,34 +145,12 @@ protected function filterProperty(string $property, $value, QueryBuilder $queryB $associationAlias = $alias; $associationField = $field; - $valueParameter = $queryNameGenerator->generateParameterName($associationField); if ($metadata->isCollectionValuedAssociation($associationField)) { $associationAlias = QueryBuilderHelper::addJoinOnce($queryBuilder, $queryNameGenerator, $alias, $associationField); $associationField = $associationFieldIdentifier; } - $type = $metadata->getTypeOfField($associationField); - - if (1 === \count($values)) { - $queryBuilder - ->andWhere($queryBuilder->expr()->eq($associationAlias.'.'.$associationField, ':'.$valueParameter)) - ->setParameter($valueParameter, $values[0], $type); - - return; - } - - $parameters = $queryBuilder->getParameters(); - $inQuery = []; - - foreach ($values as $val) { - $inQuery[] = ':'.$valueParameter; - $parameters->add(new Parameter($valueParameter, $val, $type)); - $valueParameter = $queryNameGenerator->generateParameterName($associationField); - } - - $queryBuilder - ->andWhere($associationAlias.'.'.$associationField.' IN ('.implode(', ', $inQuery).')') - ->setParameters($parameters); + $this->addWhereByStrategy($strategy, $queryBuilder, $queryNameGenerator, $associationAlias, $associationField, $values, $caseSensitive, $metadata); } /** diff --git a/tests/Bridge/Doctrine/Orm/Filter/SearchFilterTest.php b/tests/Bridge/Doctrine/Orm/Filter/SearchFilterTest.php index 8add7097424..3f74e66625b 100644 --- a/tests/Bridge/Doctrine/Orm/Filter/SearchFilterTest.php +++ b/tests/Bridge/Doctrine/Orm/Filter/SearchFilterTest.php @@ -543,11 +543,11 @@ public function provideApplyTestData(): array $filterFactory, ], 'mixed IRI and entity ID values for relations' => [ - 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), + 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), [ 'relatedDummy_p1' => 1, 'relatedDummy_p2' => 2, - 'relatedDummies_p4' => 1, + 'id_p4' => 1, ], $filterFactory, ], From 4cc887108503017574e31a549e6a9cf43aa9bf08 Mon Sep 17 00:00:00 2001 From: Alan Poulain Date: Thu, 4 Mar 2021 15:51:13 +0100 Subject: [PATCH 8/8] ci: fix PHP extensions (#4110) --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0f44c0926ce..e009e8aa5ec 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -113,7 +113,7 @@ jobs: with: php-version: ${{ matrix.php }} tools: pecl, composer - extensions: intl, bcmath, curl, openssl, mbstring + extensions: intl, bcmath, curl, openssl, mbstring, pdo_sqlite coverage: pcov ini-values: memory_limit=-1 - name: Get composer cache directory @@ -507,7 +507,7 @@ jobs: with: php-version: ${{ matrix.php }} tools: pecl, composer - extensions: intl, bcmath, curl, openssl, mbstring + extensions: intl, bcmath, curl, openssl, mbstring, mongodb coverage: none ini-values: memory_limit=-1 - name: Get composer cache directory