Skip to content

Commit

Permalink
Merge 4d2f819 into 41842c4
Browse files Browse the repository at this point in the history
  • Loading branch information
meyerbaptiste committed Feb 3, 2021
2 parents 41842c4 + 4d2f819 commit 29d534b
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 6 deletions.
Expand Up @@ -13,7 +13,7 @@

namespace ApiPlatform\Core\Bridge\Symfony\Validator\EventListener;

use ApiPlatform\Core\Bridge\Symfony\Validator\Exception\ValidationException;
use ApiPlatform\Core\Bridge\Symfony\Validator\Exception\ConstraintViolationListAwareExceptionInterface;
use ApiPlatform\Core\Util\ErrorFormatGuesser;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
Expand Down Expand Up @@ -43,7 +43,7 @@ public function __construct(SerializerInterface $serializer, array $errorFormats
public function onKernelException(ExceptionEvent $event): void
{
$exception = method_exists($event, 'getThrowable') ? $event->getThrowable() : $event->getException(); // @phpstan-ignore-line
if (!$exception instanceof ValidationException) {
if (!$exception instanceof ConstraintViolationListAwareExceptionInterface) {
return;
}
$exceptionClass = \get_class($exception);
Expand Down
@@ -0,0 +1,28 @@
<?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\Core\Bridge\Symfony\Validator\Exception;

use ApiPlatform\Core\Exception\ExceptionInterface;
use Symfony\Component\Validator\ConstraintViolationListInterface;

/**
* An exception which has a constraint violation list.
*/
interface ConstraintViolationListAwareExceptionInterface extends ExceptionInterface
{
/**
* Gets constraint violations related to this exception.
*/
public function getConstraintViolationList(): ConstraintViolationListInterface;
}
Expand Up @@ -21,7 +21,7 @@
*
* @author Kévin Dunglas <dunglas@gmail.com>
*/
final class ValidationException extends BaseValidationException
final class ValidationException extends BaseValidationException implements ConstraintViolationListAwareExceptionInterface
{
private $constraintViolationList;

Expand All @@ -32,9 +32,6 @@ public function __construct(ConstraintViolationListInterface $constraintViolatio
parent::__construct($message ?: $this->__toString(), $code, $previous);
}

/**
* Gets constraint violations related to this exception.
*/
public function getConstraintViolationList(): ConstraintViolationListInterface
{
return $this->constraintViolationList;
Expand Down
Expand Up @@ -14,15 +14,19 @@
namespace ApiPlatform\Core\Tests\Bridge\Symfony\Validator\EventListener;

use ApiPlatform\Core\Bridge\Symfony\Validator\EventListener\ValidationExceptionListener;
use ApiPlatform\Core\Bridge\Symfony\Validator\Exception\ConstraintViolationListAwareExceptionInterface;
use ApiPlatform\Core\Bridge\Symfony\Validator\Exception\ValidationException;
use ApiPlatform\Core\Tests\ProphecyTrait;
use ApiPlatform\Core\Validator\Exception\ValidationException as BaseValidationException;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Component\Validator\ConstraintViolationList;
use Symfony\Component\Validator\ConstraintViolationListInterface;
use Throwable;

/**
* @author Kévin Dunglas <dunglas@gmail.com>
Expand Down Expand Up @@ -62,4 +66,50 @@ public function testValidationException()
$this->assertSame('nosniff', $response->headers->get('X-Content-Type-Options'));
$this->assertSame('deny', $response->headers->get('X-Frame-Options'));
}

public function testOnKernelValidationExceptionWithCustomStatus(): void
{
$serializedConstraintViolationList = '{"foo": "bar"}';
$constraintViolationList = new ConstraintViolationList([]);
$exception = new class($constraintViolationList) extends BaseValidationException implements ConstraintViolationListAwareExceptionInterface {
private $constraintViolationList;

public function __construct(ConstraintViolationListInterface $constraintViolationList, $message = '', $code = 0, Throwable $previous = null)
{
parent::__construct($message, $code, $previous);

$this->constraintViolationList = $constraintViolationList;
}

public function getConstraintViolationList(): ConstraintViolationListInterface
{
return $this->constraintViolationList;
}
};

$serializerProphecy = $this->prophesize(SerializerInterface::class);
$serializerProphecy->serialize($constraintViolationList, 'hydra')->willReturn($serializedConstraintViolationList)->shouldBeCalledOnce();

$exceptionEvent = new ExceptionEvent(
$this->prophesize(HttpKernelInterface::class)->reveal(),
new Request(),
HttpKernelInterface::MASTER_REQUEST,
$exception
);

(new ValidationExceptionListener(
$serializerProphecy->reveal(),
['hydra' => ['application/ld+json']],
[\get_class($exception) => Response::HTTP_BAD_REQUEST]
))->onKernelException($exceptionEvent);

$response = $exceptionEvent->getResponse();

self::assertInstanceOf(Response::class, $response);
self::assertSame($serializedConstraintViolationList, $response->getContent());
self::assertSame(Response::HTTP_BAD_REQUEST, $response->getStatusCode());
self::assertSame('application/ld+json; charset=utf-8', $response->headers->get('Content-Type'));
self::assertSame('nosniff', $response->headers->get('X-Content-Type-Options'));
self::assertSame('deny', $response->headers->get('X-Frame-Options'));
}
}

0 comments on commit 29d534b

Please sign in to comment.