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
1 change: 1 addition & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
<directory>.</directory>
</include>
<exclude>
<directory>tests</directory>
<directory>features</directory>
<directory>vendor</directory>
<file>.php-cs-fixer.dist.php</file>
Expand Down
3 changes: 2 additions & 1 deletion src/Laravel/Exception/ErrorHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

use ApiPlatform\Laravel\ApiResource\Error;
use ApiPlatform\Laravel\Controller\ApiPlatformController;
use ApiPlatform\Metadata\Exception\InvalidUriVariableException;
use ApiPlatform\Metadata\Exception\ProblemExceptionInterface;
use ApiPlatform\Metadata\Exception\StatusAwareExceptionInterface;
use ApiPlatform\Metadata\HttpOperation;
Expand Down Expand Up @@ -192,7 +193,7 @@ private function getStatusCode(?HttpOperation $apiOperation, ?HttpOperation $err
return $exception->getStatusCode();
}

if ($exception instanceof RequestExceptionInterface) {
if ($exception instanceof RequestExceptionInterface || $exception instanceof InvalidUriVariableException) {
return 400;
}

Expand Down
3 changes: 2 additions & 1 deletion src/Symfony/EventListener/ErrorListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

use ApiPlatform\Metadata\Error as ErrorOperation;
use ApiPlatform\Metadata\Exception\HttpExceptionInterface;
use ApiPlatform\Metadata\Exception\InvalidUriVariableException;
use ApiPlatform\Metadata\Exception\ProblemExceptionInterface;
use ApiPlatform\Metadata\HttpOperation;
use ApiPlatform\Metadata\IdentifiersExtractorInterface;
Expand Down Expand Up @@ -178,7 +179,7 @@ private function getStatusCode(?HttpOperation $apiOperation, Request $request, ?
return $exception->getStatusCode();
}

if ($exception instanceof RequestExceptionInterface) {
if ($exception instanceof RequestExceptionInterface || $exception instanceof InvalidUriVariableException) {
return 400;
}

Expand Down
46 changes: 46 additions & 0 deletions tests/Fixtures/TestBundle/Entity/Issue7135/Bar.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <[email protected]>
*
* 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\Issue7135;

use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Uid\Uuid;

#[ORM\Entity()]
#[ApiResource(
shortName: 'BarPr7135',
operations: [
new Get(
uriTemplate: '/pull-request-7135/bar/{id}',
),
]
)]
#[ORM\Table(name: 'bar6466')]
class Bar
{
#[ORM\Id]
#[ORM\Column(type: 'symfony_uuid', unique: true)]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\CustomIdGenerator(class: 'doctrine.uuid_generator')]
public Uuid $id;

#[ORM\Column]
public string $title = '';

public function __construct(?Uuid $id = null)
{
$this->id = $id ?: Uuid::v7();
}
}
48 changes: 48 additions & 0 deletions tests/Fixtures/TestBundle/Entity/Issue7135/Foo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <[email protected]>
*
* 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\Issue7135;

use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Post;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Uid\Uuid;

#[ORM\Entity()]
#[ApiResource(
shortName: 'FooPr7135',
operations: [
new Post(
uriTemplate: '/pull-request-7135/foo/',
),
],
normalizationContext: ['iri_only' => true],
)]
#[ORM\Table(name: 'foo6466')]
class Foo
{
#[ORM\Id]
#[ORM\Column(type: 'symfony_uuid', unique: true)]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\CustomIdGenerator(class: 'doctrine.uuid_generator')]
public Uuid $id;

#[ORM\ManyToOne(targetEntity: Bar::class)]
#[ORM\JoinColumn(referencedColumnName: 'id', nullable: false)]
public Bar $bar;

public function __construct()
{
$this->id = Uuid::v7();
}
}
121 changes: 121 additions & 0 deletions tests/Functional/Issues/Issue7135Test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <[email protected]>
*
* 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\Issues;

use ApiPlatform\Symfony\Bundle\Test\ApiTestCase;
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Issue7135\Bar;
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Issue7135\Foo;
use ApiPlatform\Tests\RecreateSchemaTrait;
use ApiPlatform\Tests\SetupClassResourcesTrait;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Tools\SchemaTool;
use Symfony\Component\Uid\Uuid;

class Issue7135Test extends ApiTestCase
{
use RecreateSchemaTrait;
use SetupClassResourcesTrait;

protected static ?bool $alwaysBootKernel = false;

/**
* @return class-string[]
*/
public static function getResources(): array
{
return [Bar::class, Foo::class];
}

public function testValidPostRequestWithIriWhenIdentifierIsUuid(): void
{
$container = static::getContainer();
if ('mongodb' === $container->getParameter('kernel.environment')) {
$this->markTestSkipped();
}

$this->recreateSchema(self::getResources());
$bar = $this->loadBarFixture();

$response = self::createClient()->request('POST', '/pull-request-7135/foo/', [
'json' => [
'bar' => 'pull-request-7135/bar/'.$bar->id,
],
]);

self::assertEquals(201, $response->getStatusCode());
}

public function testInvalidPostRequestWithIriWhenIdentifierIsUuid(): void
{
$container = static::getContainer();
if ('mongodb' === $container->getParameter('kernel.environment')) {
$this->markTestSkipped();
}

$response = self::createClient()->request('POST', '/pull-request-7135/foo/', [
'json' => [
'bar' => 'pull-request-7135/bar/invalid-uuid',
],
]);

self::assertEquals(400, $response->getStatusCode());
self::assertJsonContains(['detail' => 'Identifier "id" could not be transformed.']);
}

public function testInvalidGetRequestWhenIdentifierIsUuid(): void
{
$container = static::getContainer();
if ('mongodb' === $container->getParameter('kernel.environment')) {
$this->markTestSkipped();
}

$response = self::createClient()->request('GET', '/pull-request-7135/bar/invalid-uuid');

self::assertEquals(404, $response->getStatusCode());
}

protected function loadBarFixture(): Bar
{
$container = static::getContainer();
$registry = $container->get('doctrine');
$manager = $registry->getManager();

$bar = new Bar(Uuid::fromString('0196b66f-66bd-780b-95fe-0ce987a32357'));
$bar->title = 'Bar one';
$manager->persist($bar);

$manager->flush();

return $bar;
}

protected function tearDown(): void
{
$container = static::getContainer();
$registry = $container->get('doctrine');
$manager = $registry->getManager();
if (!$manager instanceof EntityManagerInterface) {
return;
}

$classes = [];
foreach (self::getResources() as $entityClass) {
$classes[] = $manager->getClassMetadata($entityClass);
}

$schemaTool = new SchemaTool($manager);
@$schemaTool->dropSchema($classes);
parent::tearDown();
}
}
Loading