Skip to content
Closed
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
10 changes: 10 additions & 0 deletions src/Doctrine/Orm/Filter/IriFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,16 @@ public function apply(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $q
return;
}

if (is_iterable($value)) {
$value = array_values(array_filter(\is_array($value) ? $value : iterator_to_array($value), is_object(...)));
}

if ([] === $value || (!\is_array($value) && !\is_object($value))) {
$queryBuilder->{$context['whereClause'] ?? 'andWhere'}('1 = 0');

return;
}

// Collection associations (OneToMany/ManyToMany) require a JOIN to compare individual elements.
if ($ormLeafMetadata['is_collection_valued']) {
if (Join::LEFT_JOIN === $this->joinTypeFor($context)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public function testIriFilterCollectionJoinTypeDependsOnWhereClause(string $wher
$queryBuilder = (new QueryBuilder($entityManager))->select('o')->from(Dummy::class, 'o');
$parameter = (new QueryParameter(key: 'relatedDummies', property: 'relatedDummies'))
->withExtraProperties([
'_api_values' => 'x',
'_api_values' => new RelatedDummy(),
'nested_properties_info' => ['relatedDummies' => [
'relation_classes' => [],
'converted_relation_segments' => [],
Expand Down
36 changes: 36 additions & 0 deletions tests/Fixtures/TestBundle/Entity/Issue8834Resource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?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\IriFilter;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\QueryParameter;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity]
#[ApiResource(operations: [new Get(), new GetCollection(parameters: [
'related' => new QueryParameter(filter: new IriFilter()),
])])]
class Issue8834Resource
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
public ?int $id = null;

#[ORM\ManyToOne(targetEntity: self::class)]
public ?self $related = null;
}
57 changes: 57 additions & 0 deletions tests/Functional/Parameters/Issue8834InvalidIriTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?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\Functional\Parameters;

use ApiPlatform\Test\ApiTestCase;
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Issue8834Resource;
use ApiPlatform\Tests\RecreateSchemaTrait;
use ApiPlatform\Tests\SetupClassResourcesTrait;

final class Issue8834InvalidIriTest extends ApiTestCase
{
use RecreateSchemaTrait;
use SetupClassResourcesTrait;

protected static ?bool $alwaysBootKernel = false;

public static function getResources(): array
{
return [Issue8834Resource::class];
}

protected function setUp(): void
{
if ('mongodb' === ($_SERVER['APP_ENV'] ?? null)) {
$this->markTestSkipped('This test uses a Doctrine ORM fixture.');
}

$this->recreateSchema(self::getResources());
}

public function testInvalidIriIsIgnored(): void
{
$manager = $this->getContainer()->get('doctrine')->getManager();
$related = new Issue8834Resource();
$manager->persist($related);
$resource = new Issue8834Resource();
$resource->related = $related;
$manager->persist($resource);
$manager->flush();

self::createClient()->request('GET', '/issue8834_resources?related=/invalid/iri');

self::assertResponseStatusCodeSame(200);
self::assertJsonContains(['hydra:totalItems' => 0]);
}
}
Loading