Skip to content

Commit a7072be

Browse files
authored
fix(metadata): nested filtering only on resource classes (#7864)
1 parent 2d6e474 commit a7072be

File tree

10 files changed

+567
-1
lines changed

10 files changed

+567
-1
lines changed

src/Laravel/ApiPlatformDeferredProvider.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,8 @@ public function register(): void
267267
),
268268
$app->make('filters'),
269269
$app->make(CamelCaseToSnakeCaseNameConverter::class),
270-
$this->app->make(LoggerInterface::class)
270+
$this->app->make(LoggerInterface::class),
271+
$app->make(ResourceClassResolverInterface::class),
271272
),
272273
$app->make('filters')
273274
)

src/Metadata/Resource/Factory/ParameterResourceMetadataCollectionFactory.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
2828
use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
2929
use ApiPlatform\Metadata\Resource\ResourceMetadataCollection;
30+
use ApiPlatform\Metadata\ResourceClassResolverInterface;
3031
use ApiPlatform\Metadata\Util\ResourceClassInfoTrait;
3132
use ApiPlatform\OpenApi\Model\Parameter as OpenApiParameter;
3233
use ApiPlatform\Serializer\Filter\FilterInterface as SerializerFilterInterface;
@@ -55,7 +56,9 @@ public function __construct(
5556
private readonly ?ContainerInterface $filterLocator = null,
5657
private readonly ?NameConverterInterface $nameConverter = null,
5758
private readonly ?LoggerInterface $logger = null,
59+
?ResourceClassResolverInterface $resourceClassResolver = null,
5860
) {
61+
$this->resourceClassResolver = $resourceClassResolver;
5962
}
6063

6164
public function create(string $resourceClass): ResourceMetadataCollection

src/Symfony/Bundle/Resources/config/metadata/resource.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@
152152
service('api_platform.filter_locator')->ignoreOnInvalid(),
153153
service('api_platform.name_converter')->ignoreOnInvalid(),
154154
service('logger')->ignoreOnInvalid(),
155+
service('api_platform.resource_class_resolver')->ignoreOnInvalid(),
155156
]);
156157

157158
$services->set('api_platform.metadata.resource.metadata_collection_factory.cached', CachedResourceMetadataCollectionFactory::class)
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <dunglas@gmail.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Tests\Fixtures\TestBundle\Document;
15+
16+
use ApiPlatform\Doctrine\Odm\Filter\FreeTextQueryFilter;
17+
use ApiPlatform\Doctrine\Odm\Filter\OrFilter;
18+
use ApiPlatform\Doctrine\Odm\Filter\PartialSearchFilter;
19+
use ApiPlatform\Metadata\ApiResource;
20+
use ApiPlatform\Metadata\GetCollection;
21+
use ApiPlatform\Metadata\QueryParameter;
22+
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
23+
24+
#[ODM\Document]
25+
#[ApiResource(
26+
operations: [
27+
new GetCollection(
28+
normalizationContext: ['hydra_prefix' => false],
29+
parameters: [
30+
'search' => new QueryParameter(
31+
filter: new FreeTextQueryFilter(new OrFilter(new PartialSearchFilter(caseSensitive: true))),
32+
properties: ['content', 'tag.content'],
33+
),
34+
],
35+
),
36+
]
37+
)]
38+
class FreeTextArticle
39+
{
40+
#[ODM\Id(type: 'string', strategy: 'INCREMENT')]
41+
private ?string $id = null;
42+
43+
#[ODM\Field(type: 'string')]
44+
private string $content;
45+
46+
#[ODM\ReferenceOne(targetDocument: FreeTextTag::class)]
47+
private ?FreeTextTag $tag = null;
48+
49+
public function getId(): ?string
50+
{
51+
return $this->id;
52+
}
53+
54+
public function getContent(): string
55+
{
56+
return $this->content;
57+
}
58+
59+
public function setContent(string $content): self
60+
{
61+
$this->content = $content;
62+
63+
return $this;
64+
}
65+
66+
public function getTag(): ?FreeTextTag
67+
{
68+
return $this->tag;
69+
}
70+
71+
public function setTag(?FreeTextTag $tag): self
72+
{
73+
$this->tag = $tag;
74+
75+
return $this;
76+
}
77+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <dunglas@gmail.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Tests\Fixtures\TestBundle\Document;
15+
16+
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
17+
18+
#[ODM\Document]
19+
class FreeTextTag
20+
{
21+
#[ODM\Id(type: 'string', strategy: 'INCREMENT')]
22+
private ?string $id = null;
23+
24+
#[ODM\Field(type: 'string')]
25+
private string $content;
26+
27+
public function getId(): ?string
28+
{
29+
return $this->id;
30+
}
31+
32+
public function getContent(): string
33+
{
34+
return $this->content;
35+
}
36+
37+
public function setContent(string $content): self
38+
{
39+
$this->content = $content;
40+
41+
return $this;
42+
}
43+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <dunglas@gmail.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Tests\Fixtures\TestBundle\Document;
15+
16+
use ApiPlatform\Doctrine\Odm\Filter\FreeTextQueryFilter;
17+
use ApiPlatform\Doctrine\Odm\Filter\OrFilter;
18+
use ApiPlatform\Doctrine\Odm\Filter\PartialSearchFilter;
19+
use ApiPlatform\Metadata\ApiResource;
20+
use ApiPlatform\Metadata\GetCollection;
21+
use ApiPlatform\Metadata\QueryParameter;
22+
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
23+
24+
#[ODM\Document]
25+
#[ApiResource(
26+
shortName: 'PostCard',
27+
operations: [
28+
new GetCollection(
29+
uriTemplate: '/post_cards_embedded',
30+
normalizationContext: ['hydra_prefix' => false],
31+
parameters: [
32+
'citySearch' => new QueryParameter(
33+
filter: new PartialSearchFilter(),
34+
property: 'address.city',
35+
),
36+
'freeSearch' => new QueryParameter(
37+
filter: new FreeTextQueryFilter(new OrFilter(new PartialSearchFilter())),
38+
properties: ['address.city', 'address.street'],
39+
),
40+
],
41+
),
42+
]
43+
)]
44+
class PostCard
45+
{
46+
#[ODM\Id(type: 'string', strategy: 'INCREMENT')]
47+
private ?string $id = null;
48+
49+
#[ODM\Field(type: 'string')]
50+
private string $title;
51+
52+
#[ODM\EmbedOne(targetDocument: PostCardAddress::class)]
53+
private PostCardAddress $address;
54+
55+
public function __construct()
56+
{
57+
$this->address = new PostCardAddress();
58+
}
59+
60+
public function getId(): ?string
61+
{
62+
return $this->id;
63+
}
64+
65+
public function getTitle(): string
66+
{
67+
return $this->title;
68+
}
69+
70+
public function setTitle(string $title): self
71+
{
72+
$this->title = $title;
73+
74+
return $this;
75+
}
76+
77+
public function getAddress(): PostCardAddress
78+
{
79+
return $this->address;
80+
}
81+
82+
public function setAddress(PostCardAddress $address): self
83+
{
84+
$this->address = $address;
85+
86+
return $this;
87+
}
88+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <dunglas@gmail.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Tests\Fixtures\TestBundle\Document;
15+
16+
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
17+
18+
#[ODM\EmbeddedDocument]
19+
class PostCardAddress
20+
{
21+
#[ODM\Field(type: 'string')]
22+
private string $street;
23+
24+
#[ODM\Field(type: 'string')]
25+
private string $city;
26+
27+
#[ODM\Field(type: 'string')]
28+
private string $zipCode;
29+
30+
public function getStreet(): string
31+
{
32+
return $this->street;
33+
}
34+
35+
public function setStreet(string $street): self
36+
{
37+
$this->street = $street;
38+
39+
return $this;
40+
}
41+
42+
public function getCity(): string
43+
{
44+
return $this->city;
45+
}
46+
47+
public function setCity(string $city): self
48+
{
49+
$this->city = $city;
50+
51+
return $this;
52+
}
53+
54+
public function getZipCode(): string
55+
{
56+
return $this->zipCode;
57+
}
58+
59+
public function setZipCode(string $zipCode): self
60+
{
61+
$this->zipCode = $zipCode;
62+
63+
return $this;
64+
}
65+
}

0 commit comments

Comments
 (0)