diff --git a/features/main/exception_to_status.feature b/features/main/exception_to_status.feature
new file mode 100644
index 00000000000..203e13ea198
--- /dev/null
+++ b/features/main/exception_to_status.feature
@@ -0,0 +1,33 @@
+Feature: Using exception_to_status config
+ As an API developer
+ I can customize the status code returned if the application throws an exception
+
+ @createSchema
+ @!mongodb
+ Scenario: Configure status code via the operation exceptionToStatus to map custom NotFound error to 404
+ When I add "Content-Type" header equal to "application/ld+json"
+ And I send a "GET" request to "/dummy_exception_to_statuses/123"
+ Then the response status code should be 404
+ And the response should be in JSON
+ And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8"
+
+ @!mongodb
+ Scenario: Configure status code via the resource exceptionToStatus to map custom NotFound error to 400
+ When I add "Content-Type" header equal to "application/ld+json"
+ And I send a "PUT" request to "/dummy_exception_to_statuses/123" with body:
+ """
+ {
+ "name": "black"
+ }
+ """
+ Then the response status code should be 400
+ And the response should be in JSON
+ And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8"
+
+ @!mongodb
+ Scenario: Configure status code via the config file to map FilterValidationException to 400
+ When I add "Content-Type" header equal to "application/ld+json"
+ And I send a "GET" request to "/dummy_exception_to_statuses"
+ Then the response status code should be 400
+ And the response should be in JSON
+ And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8"
diff --git a/src/Action/ExceptionAction.php b/src/Action/ExceptionAction.php
index b5fd5f63ef9..bb6008894c3 100644
--- a/src/Action/ExceptionAction.php
+++ b/src/Action/ExceptionAction.php
@@ -96,6 +96,11 @@ public function __invoke($exception, Request $request): Response
private function getOperationExceptionToStatus(Request $request): array
{
+ // TODO: remove legacy layer in 3.0
+ if ($request->attributes->has('_api_exception_to_status')) {
+ return $request->attributes->get('_api_exception_to_status');
+ }
+
$attributes = RequestAttributesExtractor::extractAttributes($request);
if ([] === $attributes || null === $this->resourceMetadataFactory) {
diff --git a/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php b/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php
index 7de2a4a2400..4e3d565872a 100644
--- a/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php
+++ b/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php
@@ -43,6 +43,7 @@
use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaRestrictionMetadataInterface;
use ApiPlatform\Symfony\Validator\ValidationGroupsGeneratorInterface;
use Doctrine\Common\Annotations\Annotation;
+use Doctrine\Persistence\ManagerRegistry;
use phpDocumentor\Reflection\DocBlockFactoryInterface;
use Ramsey\Uuid\Uuid;
use Symfony\Component\Cache\Adapter\ArrayAdapter;
@@ -657,6 +658,11 @@ private function registerDoctrineOrmConfiguration(ContainerBuilder $container, a
return;
}
+ // For older versions of doctrine bridge this allows autoconfiguration for filters
+ if (!$container->has(ManagerRegistry::class)) {
+ $container->setAlias(ManagerRegistry::class, 'doctrine');
+ }
+
$container->registerForAutoconfiguration(QueryItemExtensionInterface::class)
->addTag('api_platform.doctrine.orm.query_extension.item');
$container->registerForAutoconfiguration(DoctrineQueryCollectionExtensionInterface::class)
diff --git a/src/Symfony/Bundle/Resources/config/api.xml b/src/Symfony/Bundle/Resources/config/api.xml
index a3d499e572f..527706249dd 100644
--- a/src/Symfony/Bundle/Resources/config/api.xml
+++ b/src/Symfony/Bundle/Resources/config/api.xml
@@ -175,5 +175,8 @@
+
+ api_platform.action.exception
+
diff --git a/src/Symfony/Bundle/Resources/config/legacy/api.xml b/src/Symfony/Bundle/Resources/config/legacy/api.xml
index cceb903baa5..51fb6e717ba 100644
--- a/src/Symfony/Bundle/Resources/config/legacy/api.xml
+++ b/src/Symfony/Bundle/Resources/config/legacy/api.xml
@@ -103,7 +103,7 @@
api_platform.action.exception
false
-
+
diff --git a/src/Symfony/Bundle/Resources/config/symfony.xml b/src/Symfony/Bundle/Resources/config/symfony.xml
index 871e3810c43..c7e5782c8ab 100644
--- a/src/Symfony/Bundle/Resources/config/symfony.xml
+++ b/src/Symfony/Bundle/Resources/config/symfony.xml
@@ -70,7 +70,7 @@
api_platform.action.exception
false
-
+
diff --git a/src/Symfony/EventListener/ErrorListener.php b/src/Symfony/EventListener/ErrorListener.php
new file mode 100644
index 00000000000..c1b4e19f3d1
--- /dev/null
+++ b/src/Symfony/EventListener/ErrorListener.php
@@ -0,0 +1,42 @@
+
+ *
+ * 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\Symfony\EventListener;
+
+use ApiPlatform\Action\ExceptionAction;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\EventListener\ErrorListener as SymfonyErrorListener;
+
+/**
+ * This error listener extends the Symfony one in order to add
+ * the `_api_operation` attribute when the request is duplicated.
+ * It will later be used to retrieve the exceptionToStatus from the operation ({@see ExceptionAction}).
+ */
+final class ErrorListener extends SymfonyErrorListener
+{
+ protected function duplicateRequest(\Throwable $exception, Request $request): Request
+ {
+ $dup = parent::duplicateRequest($exception, $request);
+
+ if ($request->attributes->has('_api_operation')) {
+ $dup->attributes->set('_api_operation', $request->attributes->get('_api_operation'));
+ }
+
+ // TODO: remove legacy layer in 3.0
+ if ($request->attributes->has('_api_exception_to_status')) {
+ $dup->attributes->set('_api_exception_to_status', $request->attributes->get('_api_exception_to_status'));
+ }
+
+ return $dup;
+ }
+}
diff --git a/src/Symfony/EventListener/ExceptionListener.php b/src/Symfony/EventListener/ExceptionListener.php
index 8afdb5b4cea..6eb340981da 100644
--- a/src/Symfony/EventListener/ExceptionListener.php
+++ b/src/Symfony/EventListener/ExceptionListener.php
@@ -28,13 +28,16 @@
final class ExceptionListener
{
/**
- * @var ErrorListener
+ * @phpstan-ignore-next-line legacy may not exist
+ *
+ * @var ErrorListener|LegacyExceptionListener
*/
private $exceptionListener;
public function __construct($controller, LoggerInterface $logger = null, $debug = false, ErrorListener $errorListener = null)
{
- $this->exceptionListener = $errorListener ? new ErrorListener($controller, $logger, $debug) : new LegacyExceptionListener($controller, $logger, $debug); // @phpstan-ignore-line
+ // @phpstan-ignore-next-line legacy may not exist
+ $this->exceptionListener = $errorListener ?: new LegacyExceptionListener($controller, $logger, $debug);
}
public function onKernelException(ExceptionEvent $event): void
@@ -48,7 +51,7 @@ public function onKernelException(ExceptionEvent $event): void
return;
}
- $this->exceptionListener->onKernelException($event);
+ $this->exceptionListener->onKernelException($event); // @phpstan-ignore-line
}
}
diff --git a/src/Symfony/Routing/ApiLoader.php b/src/Symfony/Routing/ApiLoader.php
index 8d4dd76e488..ef03a34c136 100644
--- a/src/Symfony/Routing/ApiLoader.php
+++ b/src/Symfony/Routing/ApiLoader.php
@@ -336,6 +336,7 @@ private function addRoute(RouteCollection $routeCollection, string $resourceClas
'_api_resource_class' => $resourceClass,
'_api_identifiers' => $operation['identifiers'] ?? [],
'_api_has_composite_identifier' => $operation['has_composite_identifier'] ?? true,
+ '_api_exception_to_status' => $operation['exception_to_status'] ?? $resourceMetadata->getAttribute('exception_to_status') ?? [],
'_api_operation_name' => RouteNameGenerator::generate($operationName, $resourceShortName, $operationType),
sprintf('_api_%s_operation_name', $operationType) => $operationName,
] + ($operation['defaults'] ?? []),
diff --git a/src/Test/DoctrineMongoDbOdmTestCase.php b/src/Test/DoctrineMongoDbOdmTestCase.php
index 71f613c9dd1..b2bec59a0f2 100644
--- a/src/Test/DoctrineMongoDbOdmTestCase.php
+++ b/src/Test/DoctrineMongoDbOdmTestCase.php
@@ -20,6 +20,7 @@
use Doctrine\ODM\MongoDB\Mapping\Driver\AnnotationDriver;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Cache\Adapter\ArrayAdapter;
+
use function sys_get_temp_dir;
/**
diff --git a/tests/Core/Bridge/Symfony/Routing/ApiLoaderTest.php b/tests/Core/Bridge/Symfony/Routing/ApiLoaderTest.php
index a38b5033507..accf0001be7 100644
--- a/tests/Core/Bridge/Symfony/Routing/ApiLoaderTest.php
+++ b/tests/Core/Bridge/Symfony/Routing/ApiLoaderTest.php
@@ -328,6 +328,7 @@ private function getRoute(string $path, string $controller, string $resourceClas
'_api_has_composite_identifier' => false,
sprintf('_api_%s_operation_name', $collection ? 'collection' : 'item') => $legacyOperationName,
'_api_operation_name' => $operationName,
+ '_api_exception_to_status' => [],
] + $extraDefaults,
$requirements,
$options,
diff --git a/tests/Fixtures/TestBundle/Entity/DummyExceptionToStatus.php b/tests/Fixtures/TestBundle/Entity/DummyExceptionToStatus.php
new file mode 100644
index 00000000000..92c77d04635
--- /dev/null
+++ b/tests/Fixtures/TestBundle/Entity/DummyExceptionToStatus.php
@@ -0,0 +1,116 @@
+
+ *
+ * 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\Core\Annotation\ApiFilter;
+use ApiPlatform\Core\Annotation\ApiResource;
+use ApiPlatform\Tests\Fixtures\TestBundle\Exception\NotFoundException;
+use ApiPlatform\Tests\Fixtures\TestBundle\Filter\RequiredFilter;
+use Doctrine\ORM\Mapping as ORM;
+use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
+
+/**
+ * @ApiResource(
+ * itemOperations={
+ * "get"={"exception_to_status"={NotFoundException::class=404}},
+ * "put"
+ * },
+ * collectionOperations={"get"},
+ * exceptionToStatus={
+ * NotFoundHttpException::class=400
+ * }
+ * )
+ * @ApiFilter(RequiredFilter::class)
+ * @ORM\Entity
+ */
+class DummyExceptionToStatus
+{
+ /**
+ * @var int|null The id
+ *
+ * @ORM\Column(type="integer")
+ * @ORM\Id
+ * @ORM\GeneratedValue(strategy="AUTO")
+ */
+ private $id = null;
+
+ /**
+ * @var string|null The dummy name
+ *
+ * @ORM\Column(nullable=true)
+ */
+ private $name = null;
+
+ /**
+ * @var string|null The dummy title
+ *
+ * @ORM\Column(nullable=true)
+ */
+ private $title = null;
+
+ /**
+ * @var string The dummy code
+ *
+ * @ORM\Column
+ */
+ private $code;
+
+ public function getId(): ?int
+ {
+ return $this->id;
+ }
+
+ public function setId(int $id): self
+ {
+ $this->id = $id;
+
+ return $this;
+ }
+
+ public function getName(): ?string
+ {
+ return $this->name;
+ }
+
+ public function setName(?string $name): self
+ {
+ $this->name = $name;
+
+ return $this;
+ }
+
+ public function getTitle(): ?string
+ {
+ return $this->title;
+ }
+
+ public function setTitle(?string $title): self
+ {
+ $this->title = $title;
+
+ return $this;
+ }
+
+ public function getCode(): ?string
+ {
+ return $this->code;
+ }
+
+ public function setCode(string $code): self
+ {
+ $this->code = $code;
+
+ return $this;
+ }
+}
diff --git a/tests/Fixtures/TestBundle/Exception/NotFoundException.php b/tests/Fixtures/TestBundle/Exception/NotFoundException.php
new file mode 100644
index 00000000000..b81db1bd329
--- /dev/null
+++ b/tests/Fixtures/TestBundle/Exception/NotFoundException.php
@@ -0,0 +1,22 @@
+
+ *
+ * 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\Exception;
+
+final class NotFoundException extends \Exception
+{
+ public function __construct(string $message = '', int $code = 0, ?\Throwable $previous = null)
+ {
+ parent::__construct($message, $code, $previous);
+ }
+}
diff --git a/tests/Fixtures/TestBundle/State/DummyExceptionToStatusProvider.php b/tests/Fixtures/TestBundle/State/DummyExceptionToStatusProvider.php
new file mode 100644
index 00000000000..a6ed5e23aae
--- /dev/null
+++ b/tests/Fixtures/TestBundle/State/DummyExceptionToStatusProvider.php
@@ -0,0 +1,26 @@
+
+ *
+ * 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\State;
+
+use ApiPlatform\Metadata\Operation;
+use ApiPlatform\State\ProviderInterface;
+use ApiPlatform\Tests\Fixtures\TestBundle\Exception\NotFoundException;
+
+class DummyExceptionToStatusProvider implements ProviderInterface
+{
+ public function provide(Operation $operation, array $uriVariables = [], array $context = [])
+ {
+ throw new NotFoundException();
+ }
+}
diff --git a/tests/Fixtures/app/config/config_common.yml b/tests/Fixtures/app/config/config_common.yml
index 21568e81d20..ffdcfaeff55 100644
--- a/tests/Fixtures/app/config/config_common.yml
+++ b/tests/Fixtures/app/config/config_common.yml
@@ -105,7 +105,7 @@ services:
class: 'ApiPlatform\Tests\Fixtures\TestBundle\State\AttributeResourceProvider'
public: false
tags:
- - { name: 'api_platform.state_provider' }
+ - { name: 'api_platform.state_provider' }
ApiPlatform\Tests\Fixtures\TestBundle\State\DummyCollectionDtoProvider:
class: 'ApiPlatform\Tests\Fixtures\TestBundle\State\DummyCollectionDtoProvider'
@@ -113,6 +113,10 @@ services:
tags:
- { name: 'api_platform.state_provider' }
+ ApiPlatform\Tests\Fixtures\TestBundle\State\DummyExceptionToStatusProvider:
+ tags:
+ - { name: 'api_platform.state_provider' }
+
# related_questions.state_provider:
# class: 'ApiPlatform\Tests\Fixtures\TestBundle\State\RelatedQuestionsProvider'
# public: false
@@ -127,84 +131,85 @@ services:
tags:
- { name: 'api_platform.state_processor' }
-
ApiPlatform\Tests\Fixtures\TestBundle\State\ContainNonResourceProvider:
class: 'ApiPlatform\Tests\Fixtures\TestBundle\State\ContainNonResourceProvider'
public: false
tags:
- - { name: 'api_platform.state_provider' }
+ - { name: 'api_platform.state_provider' }
ApiPlatform\Tests\Fixtures\TestBundle\State\SerializableProvider:
class: 'ApiPlatform\Tests\Fixtures\TestBundle\State\SerializableProvider'
public: false
tags:
- - { name: 'api_platform.state_provider' }
+ - { name: 'api_platform.state_provider' }
ApiPlatform\Tests\Fixtures\TestBundle\State\FakeProvider:
class: 'ApiPlatform\Tests\Fixtures\TestBundle\State\FakeProvider'
tags:
- - { name: 'api_platform.state_provider' }
+ - { name: 'api_platform.state_provider' }
ApiPlatform\Tests\Fixtures\TestBundle\State\CarProcessor:
class: 'ApiPlatform\Tests\Fixtures\TestBundle\State\CarProcessor'
tags:
- - { name: 'api_platform.state_processor' }
+ - { name: 'api_platform.state_processor' }
ApiPlatform\Tests\Fixtures\TestBundle\State\ResourceInterfaceImplementationProvider:
class: 'ApiPlatform\Tests\Fixtures\TestBundle\State\ResourceInterfaceImplementationProvider'
public: false
tags:
- - { name: 'api_platform.state_provider' }
+ - { name: 'api_platform.state_provider' }
contain_non_resource.item_data_provider:
class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataProvider\ContainNonResourceItemDataProvider'
public: false
tags:
- - { name: 'api_platform.item_data_provider' }
+ - { name: 'api_platform.item_data_provider' }
serializable.item_data_provider:
class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataProvider\SerializableItemDataProvider'
public: false
tags:
- - { name: 'api_platform.item_data_provider' }
+ - { name: 'api_platform.item_data_provider' }
resource_interface.data_provider:
class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataProvider\ResourceInterfaceImplementationDataProvider'
public: false
tags:
- - { name: 'api_platform.item_data_provider' }
- - { name: 'api_platform.collection_data_provider' }
+ - { name: 'api_platform.item_data_provider' }
+ - { name: 'api_platform.collection_data_provider' }
app.serializer.denormalizer.serializable_resource:
class: 'ApiPlatform\Tests\Fixtures\TestBundle\Serializer\Denormalizer\SerializableResourceDenormalizer'
public: false
tags:
- - { name: 'serializer.normalizer' }
+ - { name: 'serializer.normalizer' }
app.serializer.denormalizer.related_dummy_plain_identifier:
class: 'ApiPlatform\Tests\Fixtures\TestBundle\Serializer\Denormalizer\RelatedDummyPlainIdentifierDenormalizer'
public: false
arguments: ['@api_platform.iri_converter']
tags:
- - { name: 'serializer.normalizer' }
+ - { name: 'serializer.normalizer' }
app.serializer.denormalizer.dummy_plain_identifier:
class: 'ApiPlatform\Tests\Fixtures\TestBundle\Serializer\Denormalizer\DummyPlainIdentifierDenormalizer'
public: false
arguments: ['@api_platform.iri_converter']
tags:
- - { name: 'serializer.normalizer' }
+ - { name: 'serializer.normalizer' }
app.name_converter:
class: 'ApiPlatform\Tests\Fixtures\TestBundle\Serializer\NameConverter\CustomConverter'
app.my_dummy_resource.property_filter:
- parent: 'api_platform.serializer.property_filter'
- tags: [ { name: 'api_platform.filter', id: 'my_dummy.property' } ]
+ parent: 'api_platform.serializer.property_filter'
+ tags:
+ - { name: 'api_platform.filter', id: 'my_dummy.property' }
app.dummy_travel_resource.property_filter:
parent: 'api_platform.serializer.property_filter'
- tags: [ { name: 'api_platform.filter', id: 'dummy_travel.property' } ]
+ tags:
+ - { name: 'api_platform.filter', id: 'dummy_travel.property' }
ApiPlatform\Tests\Fixtures\TestBundle\Filter\RequiredFilter:
arguments: ['@doctrine']
@@ -216,19 +221,19 @@ services:
ApiPlatform\Tests\Fixtures\TestBundle\Filter\RequiredAllowEmptyFilter:
arguments: [ '@doctrine' ]
- tags: [ 'api_platform.filter' ]
+ tags: ['api_platform.filter']
ApiPlatform\Tests\Fixtures\TestBundle\Filter\BoundsFilter:
arguments: [ '@doctrine' ]
- tags: [ 'api_platform.filter' ]
+ tags: ['api_platform.filter']
ApiPlatform\Tests\Fixtures\TestBundle\Filter\LengthFilter:
arguments: [ '@doctrine' ]
- tags: [ 'api_platform.filter' ]
+ tags: ['api_platform.filter']
ApiPlatform\Tests\Fixtures\TestBundle\Filter\PatternFilter:
arguments: [ '@doctrine' ]
- tags: [ 'api_platform.filter' ]
+ tags: ['api_platform.filter']
ApiPlatform\Tests\Fixtures\TestBundle\Controller\:
resource: '../../TestBundle/Controller'
@@ -238,15 +243,15 @@ services:
ApiPlatform\Tests\Fixtures\TestBundle\Filter\EnumFilter:
arguments: [ '@doctrine' ]
- tags: [ 'api_platform.filter' ]
+ tags: ['api_platform.filter']
ApiPlatform\Tests\Fixtures\TestBundle\Filter\MultipleOfFilter:
arguments: [ '@doctrine' ]
- tags: [ 'api_platform.filter' ]
+ tags: ['api_platform.filter']
ApiPlatform\Tests\Fixtures\TestBundle\Filter\ArrayItemsFilter:
arguments: [ '@doctrine' ]
- tags: [ 'api_platform.filter' ]
+ tags: ['api_platform.filter']
app.config_dummy_resource.action:
class: 'ApiPlatform\Tests\Fixtures\TestBundle\Action\ConfigCustom'
@@ -254,37 +259,44 @@ services:
public: true
app.entity.filter.dummy_property.property:
- parent: 'api_platform.serializer.property_filter'
- tags: [ { name: 'api_platform.filter', id: 'dummy_property.property' } ]
+ parent: 'api_platform.serializer.property_filter'
+ tags:
+ - { name: 'api_platform.filter', id: 'dummy_property.property' }
app.entity.filter.dummy_property.whitelist_property:
- parent: 'api_platform.serializer.property_filter'
+ parent: 'api_platform.serializer.property_filter'
arguments: [ 'whitelisted_properties', false, [foo, nameConverted] ]
- tags: [ { name: 'api_platform.filter', id: 'dummy_property.whitelist_property' } ]
+ tags:
+ - { name: 'api_platform.filter', id: 'dummy_property.whitelist_property' }
app.entity.filter.dummy_property.whitelist_nested_property:
- parent: 'api_platform.serializer.property_filter'
+ parent: 'api_platform.serializer.property_filter'
arguments: [ 'whitelisted_nested_properties', false, {foo: ~, group: [baz, qux]} ]
- tags: [ { name: 'api_platform.filter', id: 'dummy_property.whitelisted_properties' } ]
+ tags:
+ - { name: 'api_platform.filter', id: 'dummy_property.whitelisted_properties' }
app.entity.filter.dummy_group.group:
- parent: 'api_platform.serializer.group_filter'
- tags: [ { name: 'api_platform.filter', id: 'dummy_group.group' } ]
+ parent: 'api_platform.serializer.group_filter'
+ tags:
+ - { name: 'api_platform.filter', id: 'dummy_group.group' }
app.entity.filter.dummy_group.override_group:
- parent: 'api_platform.serializer.group_filter'
+ parent: 'api_platform.serializer.group_filter'
arguments: [ 'override_groups', true ]
- tags: [ { name: 'api_platform.filter', id: 'dummy_group.override_group' } ]
+ tags:
+ - { name: 'api_platform.filter', id: 'dummy_group.override_group' }
app.entity.filter.dummy_group.whitelist_group:
- parent: 'api_platform.serializer.group_filter'
+ parent: 'api_platform.serializer.group_filter'
arguments: [ 'whitelisted_groups', false, ['dummy_foo', 'dummy_baz'] ]
- tags: [ { name: 'api_platform.filter', id: 'dummy_group.whitelist_group' } ]
+ tags:
+ - { name: 'api_platform.filter', id: 'dummy_group.whitelist_group' }
app.entity.filter.dummy_group.override_whitelist_group:
- parent: 'api_platform.serializer.group_filter'
+ parent: 'api_platform.serializer.group_filter'
arguments: [ 'override_whitelisted_groups', true, ['dummy_foo', 'dummy_baz'] ]
- tags: [ { name: 'api_platform.filter', id: 'dummy_group.override_whitelist_group' } ]
+ tags:
+ - { name: 'api_platform.filter', id: 'dummy_group.override_whitelist_group' }
logger:
class: Psr\Log\NullLogger
@@ -318,13 +330,13 @@ services:
class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\CustomInputDtoDataTransformer'
public: false
tags:
- - { name: 'api_platform.data_transformer' }
+ - { name: 'api_platform.data_transformer' }
app.data_transformer.custom_output_dto:
class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\CustomOutputDtoDataTransformer'
public: false
tags:
- - { name: 'api_platform.data_transformer' }
+ - { name: 'api_platform.data_transformer' }
app.data_transformer.custom_output_dto_fallback_same_class:
class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\OutputDtoSameClassTransformer'
@@ -336,43 +348,43 @@ services:
class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\InputDtoDataTransformer'
public: false
tags:
- - { name: 'api_platform.data_transformer' }
+ - { name: 'api_platform.data_transformer' }
app.data_transformer.output_dto:
class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\OutputDtoDataTransformer'
public: false
tags:
- - { name: 'api_platform.data_transformer' }
+ - { name: 'api_platform.data_transformer' }
app.data_transformer.dummy_dto_no_input_to_output_dto:
class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\DummyDtoNoInputToOutputDtoDataTransformer'
public: false
tags:
- - { name: 'api_platform.data_transformer' }
+ - { name: 'api_platform.data_transformer' }
app.data_transformer.recover_password_input:
class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\RecoverPasswordInputDataTransformer'
public: false
tags:
- - { name: 'api_platform.data_transformer' }
+ - { name: 'api_platform.data_transformer' }
app.data_transformer.recover_password_output:
class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\RecoverPasswordOutputDataTransformer'
public: false
tags:
- - { name: 'api_platform.data_transformer' }
+ - { name: 'api_platform.data_transformer' }
app.data_transformer.initialize_input:
class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\InitializeInputDataTransformer'
public: false
tags:
- - { name: 'api_platform.data_transformer' }
+ - { name: 'api_platform.data_transformer' }
app.messenger_handler.messenger_with_response:
class: 'ApiPlatform\Tests\Fixtures\TestBundle\MessengerHandler\MessengerWithResponseHandler'
public: false
tags:
- - { name: 'messenger.message_handler' }
+ - { name: 'messenger.message_handler' }
app.graphql.query_resolver.dummy_custom_item:
class: 'ApiPlatform\Tests\Fixtures\TestBundle\GraphQl\Resolver\DummyCustomQueryItemResolver'
@@ -438,7 +450,7 @@ services:
class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\RPCOutputDataTransformer'
public: false
tags:
- - { name: 'api_platform.data_transformer' }
+ - { name: 'api_platform.data_transformer' }
app.security.authentication_entrypoint:
class: 'ApiPlatform\Tests\Fixtures\TestBundle\Security\AuthenticationEntryPoint'
diff --git a/tests/Symfony/EventListener/ExceptionListenerTest.php b/tests/Symfony/EventListener/ExceptionListenerTest.php
index afc5223240a..06d66ab5dff 100644
--- a/tests/Symfony/EventListener/ExceptionListenerTest.php
+++ b/tests/Symfony/EventListener/ExceptionListenerTest.php
@@ -14,11 +14,10 @@
namespace ApiPlatform\Tests\Symfony\EventListener;
use ApiPlatform\Core\Tests\ProphecyTrait;
+use ApiPlatform\Metadata\Get;
use ApiPlatform\Symfony\EventListener\ExceptionListener;
use PHPUnit\Framework\TestCase;
-use Prophecy\Argument;
use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\EventListener\ErrorListener;
use Symfony\Component\HttpKernel\HttpKernelInterface;
@@ -36,20 +35,23 @@ class ExceptionListenerTest extends TestCase
public function testOnKernelException(Request $request)
{
$kernel = $this->prophesize(HttpKernelInterface::class);
- $kernel->handle(Argument::type(Request::class), HttpKernelInterface::SUB_REQUEST, false)->willReturn(new Response())->shouldBeCalled();
- $listener = new ExceptionListener('foo:bar', null, false, class_exists(ErrorListener::class) ? $this->prophesize(ErrorListener::class)->reveal() : null);
+ $errorListener = class_exists(ErrorListener::class) ? $this->prophesize(ErrorListener::class) : null;
+
$event = new ExceptionEvent($kernel->reveal(), $request, \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, new \Exception());
- $listener->onKernelException($event);
- $this->assertInstanceOf(Response::class, $event->getResponse());
+ if ($errorListener) {
+ $errorListener->onKernelException($event)->shouldBeCalled();
+ }
+
+ $listener = new ExceptionListener('foo:bar', null, false, $errorListener ? $errorListener->reveal() : null);
+ $listener->onKernelException($event);
}
public function getRequest()
{
return [
- [new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get'])],
- [new Request([], [], ['_api_respond' => true])],
+ [new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation' => new Get(), '_api_respond' => true])],
];
}