Skip to content

Commit

Permalink
feat(serializer): support for getSupportedTypes (symfony 6.3) (#5671)
Browse files Browse the repository at this point in the history
  • Loading branch information
mrossard authored Jul 20, 2023
1 parent e21e9fa commit 011fd48
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 3 deletions.
9 changes: 9 additions & 0 deletions features/doctrine/search_filter.feature
Original file line number Diff line number Diff line change
Expand Up @@ -1033,3 +1033,12 @@ Feature: Search filter on collections
Then the response status code should be 200
And the response should be in JSON
And the JSON node "hydra:totalItems" should be equal to 1

@!mongodb
@createSchema
Scenario: Custom search filters can use Doctrine Expressions as join conditions
Given there is a dummy object with 3 relatedDummies and their thirdLevel
When I send a "GET" request to "/dummy_ressource_with_custom_filter?custom=3"
Then the response status code should be 200
And the response should be in JSON
And the JSON node "hydra:totalItems" should be equal to 1
7 changes: 4 additions & 3 deletions src/Doctrine/Orm/Extension/FilterEagerLoadingExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -167,12 +167,13 @@ private function getQueryBuilderWithNewAliases(QueryBuilder $queryBuilder, Query
/** @var Join $joinPart */
$joinString = preg_replace($this->buildReplacePatterns($aliases), $replacements, $joinPart->getJoin());
$pos = strpos($joinString, '.');
$joinCondition = (string) $joinPart->getCondition();
if (false === $pos) {
if (null !== $joinPart->getCondition() && null !== $this->resourceClassResolver && $this->resourceClassResolver->isResourceClass($joinString)) {
if ($joinCondition && $this->resourceClassResolver?->isResourceClass($joinString)) {
$newAlias = $queryNameGenerator->generateJoinAlias($joinPart->getAlias());
$aliases[] = "{$joinPart->getAlias()}.";
$replacements[] = "$newAlias.";
$condition = preg_replace($this->buildReplacePatterns($aliases), $replacements, $joinPart->getCondition());
$condition = preg_replace($this->buildReplacePatterns($aliases), $replacements, $joinCondition);
$join = new Join($joinPart->getJoinType(), $joinPart->getJoin(), $newAlias, $joinPart->getConditionType(), $condition);
$queryBuilderClone->add('join', [$replacement => $join], true); // @phpstan-ignore-line
}
Expand All @@ -184,7 +185,7 @@ private function getQueryBuilderWithNewAliases(QueryBuilder $queryBuilder, Query
$newAlias = $queryNameGenerator->generateJoinAlias($association);
$aliases[] = "{$joinPart->getAlias()}.";
$replacements[] = "$newAlias.";
$condition = preg_replace($this->buildReplacePatterns($aliases), $replacements, $joinPart->getCondition() ?? '');
$condition = preg_replace($this->buildReplacePatterns($aliases), $replacements, $joinCondition);
QueryBuilderHelper::addJoinOnce($queryBuilderClone, $queryNameGenerator, $alias, $association, $joinPart->getJoinType(), $joinPart->getConditionType(), $condition, $originAlias, $newAlias);
}

Expand Down
44 changes: 44 additions & 0 deletions tests/Fixtures/TestBundle/ApiResource/Issue5648/CustomFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?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\ApiResource\Issue5648;

use ApiPlatform\Doctrine\Orm\Filter\AbstractFilter;
use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use ApiPlatform\Metadata\Operation;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder;

class CustomFilter extends AbstractFilter
{
protected function filterProperty(string $property, $value, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, Operation $operation = null, array $context = []): void
{
if ('custom' !== $property) {
return;
}

$alias = $queryBuilder->getRootAliases()[0];
$secondAlias = $queryNameGenerator->generateJoinAlias('relatedDummies');

$joinCondition = $queryBuilder->expr()->like(sprintf('%s.name', $secondAlias), ':param');

$queryBuilder->join(sprintf('%s.relatedDummies', $alias), $secondAlias, Join::WITH, $joinCondition)
->setParameter('param', '%'.$value.'%')
->andWhere('1=1'); // problem only gets triggered when there is a where part.
}

public function getDescription(string $resourceClass): array
{
return [];
}
}
40 changes: 40 additions & 0 deletions tests/Fixtures/TestBundle/ApiResource/Issue5648/DummyResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?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\ApiResource\Issue5648;

use ApiPlatform\Doctrine\Orm\State\Options;
use ApiPlatform\Metadata\ApiFilter;
use ApiPlatform\Metadata\ApiProperty;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy;

#[ApiResource(
operations: [
new GetCollection(uriTemplate: '/dummy_ressource_with_custom_filter', itemUriTemplate: '/dummy_ressource_with_custom_filter/{id}'),
new Get(uriTemplate: '/dummy_ressource_with_custom_filter/{id}', uriVariables: ['id']),
],
stateOptions: new Options(entityClass: Dummy::class)
)]
#[ApiFilter(CustomFilter::class)]
class DummyResource
{
#[ApiProperty(identifier: true)]
public ?int $id = null;

public string $name;

public array $relatedDummies;
}

0 comments on commit 011fd48

Please sign in to comment.