Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
869 changes: 0 additions & 869 deletions filters.md

This file was deleted.

25 changes: 25 additions & 0 deletions src/Doctrine/Common/Filter/NameConverterAwareInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\Doctrine\Common\Filter;

use Symfony\Component\Serializer\NameConverter\NameConverterInterface;

interface NameConverterAwareInterface
{
public function hasNameConverter(): bool;

public function getNameConverter(): ?NameConverterInterface;

public function setNameConverter(NameConverterInterface $nameConverter): void;
}
7 changes: 7 additions & 0 deletions src/Doctrine/Common/ParameterExtensionTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@

use ApiPlatform\Doctrine\Common\Filter\LoggerAwareInterface;
use ApiPlatform\Doctrine\Common\Filter\ManagerRegistryAwareInterface;
use ApiPlatform\Doctrine\Common\Filter\NameConverterAwareInterface;
use ApiPlatform\Doctrine\Common\Filter\PropertyAwareFilterInterface;
use ApiPlatform\Metadata\Parameter;
use Doctrine\Persistence\ManagerRegistry;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;

trait ParameterExtensionTrait
{
Expand All @@ -28,6 +30,7 @@ trait ParameterExtensionTrait
protected ContainerInterface $filterLocator;
protected ?ManagerRegistry $managerRegistry = null;
protected ?LoggerInterface $logger = null;
protected ?NameConverterInterface $nameConverter = null;

/**
* @param object $filter the filter instance to configure
Expand All @@ -43,6 +46,10 @@ private function configureFilter(object $filter, Parameter $parameter): void
$filter->setLogger($this->logger);
}

if ($this->nameConverter && $filter instanceof NameConverterAwareInterface && !$filter->hasNameConverter()) {
$filter->setNameConverter($this->nameConverter);
}

if ($filter instanceof PropertyAwareFilterInterface) {
$properties = [];
// Check if the filter has getProperties method (e.g., if it's an AbstractFilter)
Expand Down
3 changes: 3 additions & 0 deletions src/Doctrine/Odm/Extension/ParameterExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use Doctrine\ODM\MongoDB\Aggregation\Builder;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;

/**
* Reads operation parameters and execute its filter.
Expand All @@ -36,10 +37,12 @@ public function __construct(
ContainerInterface $filterLocator,
?ManagerRegistry $managerRegistry = null,
?LoggerInterface $logger = null,
?NameConverterInterface $nameConverter = null,
) {
$this->filterLocator = $filterLocator;
$this->managerRegistry = $managerRegistry;
$this->logger = $logger;
$this->nameConverter = $nameConverter;
}

/**
Expand Down
18 changes: 17 additions & 1 deletion src/Doctrine/Odm/Filter/AbstractFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
namespace ApiPlatform\Doctrine\Odm\Filter;

use ApiPlatform\Doctrine\Common\Filter\ManagerRegistryAwareInterface;
use ApiPlatform\Doctrine\Common\Filter\NameConverterAwareInterface;
use ApiPlatform\Doctrine\Common\Filter\PropertyAwareFilterInterface;
use ApiPlatform\Doctrine\Common\PropertyHelperTrait;
use ApiPlatform\Doctrine\Odm\PropertyHelperTrait as MongoDbOdmPropertyHelperTrait;
Expand All @@ -32,7 +33,7 @@
*
* @author Alan Poulain <contact@alanpoulain.eu>
*/
abstract class AbstractFilter implements FilterInterface, PropertyAwareFilterInterface, ManagerRegistryAwareInterface
abstract class AbstractFilter implements FilterInterface, PropertyAwareFilterInterface, ManagerRegistryAwareInterface, NameConverterAwareInterface
{
use MongoDbOdmPropertyHelperTrait;
use PropertyHelperTrait;
Expand Down Expand Up @@ -85,6 +86,21 @@ public function setManagerRegistry(ManagerRegistry $managerRegistry): void
$this->managerRegistry = $managerRegistry;
}

public function hasNameConverter(): bool
{
return $this->nameConverter instanceof NameConverterInterface;
}

public function getNameConverter(): ?NameConverterInterface
{
return $this->nameConverter;
}

public function setNameConverter(NameConverterInterface $nameConverter): void
{
$this->nameConverter = $nameConverter;
}

/**
* @return array<string, mixed>|null
*/
Expand Down
58 changes: 58 additions & 0 deletions src/Doctrine/Odm/Tests/Extension/ParameterExtensionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use ApiPlatform\Doctrine\Common\Filter\LoggerAwareTrait;
use ApiPlatform\Doctrine\Common\Filter\ManagerRegistryAwareInterface;
use ApiPlatform\Doctrine\Common\Filter\ManagerRegistryAwareTrait;
use ApiPlatform\Doctrine\Common\Filter\NameConverterAwareInterface;
use ApiPlatform\Doctrine\Odm\Extension\ParameterExtension;
use ApiPlatform\Doctrine\Odm\Filter\FilterInterface;
use ApiPlatform\Metadata\BackwardCompatibleFilterDescriptionTrait;
Expand All @@ -30,6 +31,7 @@
use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;

class ParameterExtensionTest extends TestCase
{
Expand Down Expand Up @@ -123,6 +125,62 @@ public function apply(Builder $aggregationBuilder, string $resourceClass, ?Opera
$this->assertNotNull($filter->getManagerRegistry());
}

public function testApplyToCollectionWithNameConverter(): void
{
$aggregationBuilder = $this->createMock(Builder::class);
$nameConverter = $this->createMock(NameConverterInterface::class);

$filter = new class($nameConverter) implements FilterInterface, NameConverterAwareInterface {
use BackwardCompatibleFilterDescriptionTrait;

private ?NameConverterInterface $nameConverter = null;

public function __construct(private readonly NameConverterInterface $expectedNameConverter)
{
}

public function hasNameConverter(): bool
{
return $this->nameConverter instanceof NameConverterInterface;
}

public function getNameConverter(): ?NameConverterInterface
{
return $this->nameConverter;
}

public function setNameConverter(NameConverterInterface $nameConverter): void
{
$this->nameConverter = $nameConverter;
}

public function apply(Builder $aggregationBuilder, string $resourceClass, ?Operation $operation = null, array &$context = []): void
{
Assert::assertTrue($this->hasNameConverter());
Assert::assertSame($this->expectedNameConverter, $this->getNameConverter());
Assert::assertSame('SomeClass', $resourceClass);
}
};

$operation = (new GetCollection())
->withParameters([
(new QueryParameter(
key: 'param1',
filter: $filter,
))->setValue(1),
]);

$extension = new ParameterExtension(
$this->createNonCalledFilterLocator(),
nameConverter: $nameConverter,
);
$context = [];
$extension->applyToCollection($aggregationBuilder, 'SomeClass', $operation, $context);

$this->assertSame([], $context);
$this->assertSame($nameConverter, $filter->getNameConverter());
}

public function testApplyToCollectionPassesContext(): void
{
$aggregationBuilder = $this->createMock(Builder::class);
Expand Down
2 changes: 1 addition & 1 deletion src/Doctrine/Odm/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
],
"require": {
"php": ">=8.2",
"api-platform/doctrine-common": "^4.2.9",
"api-platform/doctrine-common": "^4.2.23",
"api-platform/metadata": "^4.2",
"api-platform/state": "^4.2.4",
"doctrine/mongodb-odm": "^2.10",
Expand Down
3 changes: 3 additions & 0 deletions src/Doctrine/Orm/Extension/ParameterExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use Doctrine\Persistence\ManagerRegistry;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;

/**
* Reads operation parameters and execute its filter.
Expand All @@ -36,10 +37,12 @@ public function __construct(
ContainerInterface $filterLocator,
?ManagerRegistry $managerRegistry = null,
?LoggerInterface $logger = null,
?NameConverterInterface $nameConverter = null,
) {
$this->filterLocator = $filterLocator;
$this->managerRegistry = $managerRegistry;
$this->logger = $logger;
$this->nameConverter = $nameConverter;
}

/**
Expand Down
18 changes: 17 additions & 1 deletion src/Doctrine/Orm/Filter/AbstractFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
namespace ApiPlatform\Doctrine\Orm\Filter;

use ApiPlatform\Doctrine\Common\Filter\ManagerRegistryAwareInterface;
use ApiPlatform\Doctrine\Common\Filter\NameConverterAwareInterface;
use ApiPlatform\Doctrine\Common\Filter\PropertyAwareFilterInterface;
use ApiPlatform\Doctrine\Common\PropertyHelperTrait;
use ApiPlatform\Doctrine\Orm\PropertyHelperTrait as OrmPropertyHelperTrait;
Expand All @@ -26,7 +27,7 @@
use Psr\Log\NullLogger;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;

abstract class AbstractFilter implements FilterInterface, PropertyAwareFilterInterface, ManagerRegistryAwareInterface
abstract class AbstractFilter implements FilterInterface, PropertyAwareFilterInterface, ManagerRegistryAwareInterface, NameConverterAwareInterface
{
use OrmPropertyHelperTrait;
use PropertyHelperTrait;
Expand Down Expand Up @@ -78,6 +79,21 @@ public function setManagerRegistry(ManagerRegistry $managerRegistry): void
$this->managerRegistry = $managerRegistry;
}

public function hasNameConverter(): bool
{
return $this->nameConverter instanceof NameConverterInterface;
}

public function getNameConverter(): ?NameConverterInterface
{
return $this->nameConverter;
}

public function setNameConverter(NameConverterInterface $nameConverter): void
{
$this->nameConverter = $nameConverter;
}

public function getProperties(): ?array
{
return $this->properties;
Expand Down
2 changes: 1 addition & 1 deletion src/Doctrine/Orm/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
],
"require": {
"php": ">=8.2",
"api-platform/doctrine-common": "^4.2.9",
"api-platform/doctrine-common": "^4.2.23",
"api-platform/metadata": "^4.2",
"api-platform/state": "^4.2.4",
"doctrine/orm": "^2.17 || ^3.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@
service('api_platform.filter_locator'),
service('doctrine_mongodb')->nullOnInvalid(),
service('logger')->nullOnInvalid(),
service('api_platform.name_converter')->nullOnInvalid(),
])
->tag('api_platform.doctrine_mongodb.odm.aggregation_extension.collection', ['priority' => 32])
->tag('api_platform.doctrine_mongodb.odm.aggregation_extension.item');
Expand Down
1 change: 1 addition & 0 deletions src/Symfony/Bundle/Resources/config/doctrine_orm.php
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@
service('api_platform.filter_locator'),
service('doctrine')->nullOnInvalid(),
service('logger')->nullOnInvalid(),
service('api_platform.name_converter')->nullOnInvalid(),
])
->tag('api_platform.doctrine.orm.query_extension.collection', ['priority' => -16])
->tag('api_platform.doctrine.orm.query_extension.item', ['priority' => -9]);
Expand Down
51 changes: 51 additions & 0 deletions tests/Fixtures/TestBundle/Document/ConvertedDateParameter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\Tests\Fixtures\TestBundle\Document;

use ApiPlatform\Doctrine\Odm\Filter\DateFilter;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\QueryParameter;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;

/**
* Tests that legacy AbstractFilter subclasses work with QueryParameter
* when a nameConverter is configured (issue #7866).
*/
#[ApiResource(
operations: [
new GetCollection(
parameters: [
'nameConverted' => new QueryParameter(
filter: new DateFilter(),
properties: ['nameConverted'],
),
],
),
],
)]
#[ODM\Document]
class ConvertedDateParameter
{
#[ODM\Id(strategy: 'INCREMENT', type: 'int')]
private ?int $id = null;

#[ODM\Field(type: 'date')]
public \DateTime $nameConverted;

public function getId(): ?int
{
return $this->id;
}
}
53 changes: 53 additions & 0 deletions tests/Fixtures/TestBundle/Entity/ConvertedDateParameter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity;

use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\QueryParameter;
use Doctrine\ORM\Mapping as ORM;

/**
* Tests that legacy AbstractFilter subclasses work with QueryParameter
* when a nameConverter is configured (issue #7866).
*/
#[ApiResource(
operations: [
new GetCollection(
parameters: [
'nameConverted' => new QueryParameter(
filter: new DateFilter(),
properties: ['nameConverted'],
),
],
),
],
)]
#[ORM\Entity]
class ConvertedDateParameter
{
#[ORM\Column(type: 'integer', nullable: true)]
#[ORM\Id]
#[ORM\GeneratedValue(strategy: 'AUTO')]
private ?int $id = null;

#[ORM\Column(type: 'date')]
public \DateTime $nameConverted;

public function getId(): ?int
{
return $this->id;
}
}
Loading
Loading