Skip to content

Commit 373af5b

Browse files
committed
Refactor RequestAttributesExtractor to use explicit keys
1 parent 2bc1754 commit 373af5b

24 files changed

+128
-115
lines changed

src/Action/GetCollectionAction.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ public function __construct(CollectionDataProviderInterface $collectionDataProvi
4242
*/
4343
public function __invoke(Request $request)
4444
{
45-
list($resourceClass, $operationName) = RequestAttributesExtractor::extractAttributes($request);
45+
$attributes = RequestAttributesExtractor::extractAttributes($request);
4646

47-
return $this->collectionDataProvider->getCollection($resourceClass, $operationName);
47+
return $this->collectionDataProvider->getCollection($attributes['resource_class'], $attributes['collection_operation_name']);
4848
}
4949
}

src/Action/GetItemAction.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ public function __construct(ItemDataProviderInterface $itemDataProvider)
4444
*/
4545
public function __invoke(Request $request, $id)
4646
{
47-
list($resourceClass, , $operationName) = RequestAttributesExtractor::extractAttributes($request);
47+
$attributes = RequestAttributesExtractor::extractAttributes($request);
4848

49-
$data = $this->itemDataProvider->getItem($resourceClass, $id, $operationName, true);
49+
$data = $this->itemDataProvider->getItem($attributes['resource_class'], $id, $attributes['item_operation_name'], true);
5050
if (!$data) {
5151
throw new NotFoundHttpException('Not Found');
5252
}

src/Api/RequestAttributesExtractor.php

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,34 +23,44 @@
2323
*/
2424
final class RequestAttributesExtractor
2525
{
26+
const API_ATTRIBUTES = ['resource_class', 'format', 'mime_type'];
27+
2628
/**
27-
* Extracts resource class, operation name and format request attributes. Throws an exception if the request does not contain required
28-
* attributes.
29+
* Extracts resource class, operation name and format request attributes. Throws an exception if the request does not
30+
* contain required attributes.
2931
*
3032
* @param Request $request
3133
*
3234
* @throws RuntimeException
3335
*
34-
* @return array [$resourceClass, $collectionOperation, $itemOperation, $format]
36+
* @return array
3537
*/
3638
public static function extractAttributes(Request $request)
3739
{
38-
$resourceClass = $request->attributes->get('_resource_class');
39-
if (!$resourceClass) {
40-
throw new RuntimeException('The request attribute "_resource_class" must be defined.');
41-
}
40+
$result = [];
41+
42+
foreach (self::API_ATTRIBUTES as $key) {
43+
$attributeKey = '_api_'.$key;
44+
$attributeValue = $request->attributes->get($attributeKey);
4245

43-
$collectionOperation = $request->attributes->get('_collection_operation_name');
44-
$itemOperation = $request->attributes->get('_item_operation_name');
45-
if (!$itemOperation && !$collectionOperation) {
46-
throw new RuntimeException('One of the request attribute "_item_operation_name" or "_collection_operation_name" must be defined.');
46+
if (null === $attributeValue) {
47+
throw new RuntimeException(sprintf('The request attribute "%s" must be defined.', $attributeKey));
48+
}
49+
50+
$result[$key] = $attributeValue;
4751
}
4852

49-
$format = $request->attributes->get('_api_format');
50-
if (!$format) {
51-
throw new RuntimeException('The request attribute "_api_format" must be defined.');
53+
$collectionOperationName = $request->attributes->get('_api_collection_operation_name');
54+
$itemOperationName = $request->attributes->get('_api_item_operation_name');
55+
56+
if ($collectionOperationName) {
57+
$result['collection_operation_name'] = $collectionOperationName;
58+
} elseif ($itemOperationName) {
59+
$result['item_operation_name'] = $itemOperationName;
60+
} else {
61+
throw new RuntimeException('One of the request attribute "_api_collection_operation_name" or "_api_item_operation_name" must be defined.');
5262
}
5363

54-
return [$resourceClass, $collectionOperation, $itemOperation, $format];
64+
return $result;
5565
}
5666
}

src/Bridge/Doctrine/EventListener/ManagerViewListener.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,16 @@ public function __construct(ManagerRegistry $managerRegistry)
4040
public function onKernelView(GetResponseForControllerResultEvent $event)
4141
{
4242
$request = $event->getRequest();
43-
if (!in_array($request->getMethod(), [Request::METHOD_POST, Request::METHOD_PUT, Request::METHOD_DELETE])) {
43+
if (!in_array($request->getMethod(), [Request::METHOD_POST, Request::METHOD_PUT, Request::METHOD_DELETE], true)) {
4444
return;
4545
}
4646

47-
$resourceClass = $request->attributes->get('_resource_class');
48-
if (!$resourceClass) {
47+
$resourceClass = $request->attributes->get('_api_resource_class');
48+
if (null === $resourceClass) {
4949
return;
5050
}
5151

5252
$controllerResult = $event->getControllerResult();
53-
5453
if (null === $objectManager = $this->getManager($resourceClass, $controllerResult)) {
5554
return $controllerResult;
5655
}

src/Bridge/Symfony/Routing/ApiLoader.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ final class ApiLoader extends Loader
3535
const ROUTE_NAME_PREFIX = 'api_';
3636
const DEFAULT_ACTION_PATTERN = 'api_platform.action.';
3737

38-
private $kernel;
3938
private $fileLoader;
4039
private $resourceNameCollectionFactory;
4140
private $resourceMetadataFactory;
@@ -44,11 +43,11 @@ final class ApiLoader extends Loader
4443

4544
public function __construct(KernelInterface $kernel, ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, ResourceMetadataFactoryInterface $resourceMetadataFactory, ResourcePathGeneratorInterface $resourcePathGenerator, ContainerInterface $container)
4645
{
47-
$this->container = $container;
4846
$this->fileLoader = new XmlFileLoader(new FileLocator($kernel->locateResource('@ApiPlatformBundle/Resources/config/routing')));
4947
$this->resourceNameCollectionFactory = $resourceNameCollectionFactory;
5048
$this->resourceMetadataFactory = $resourceMetadataFactory;
5149
$this->resourcePathGenerator = $resourcePathGenerator;
50+
$this->container = $container;
5251
}
5352

5453
/**
@@ -144,8 +143,8 @@ private function addRoute(RouteCollection $routeCollection, string $resourceClas
144143
$path,
145144
[
146145
'_controller' => $controller,
147-
'_resource_class' => $resourceClass,
148-
sprintf('_%s_operation_name', $collection ? 'collection' : 'item') => $operationName,
146+
'_api_resource_class' => $resourceClass,
147+
sprintf('_api_%s_operation_name', $collection ? 'collection' : 'item') => $operationName,
149148
],
150149
[],
151150
[],

src/Bridge/Symfony/Routing/IriConverter.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,11 @@ public function getItemFromIri(string $iri, bool $fetchData = false)
5858
throw new InvalidArgumentException(sprintf('No route matches "%s".', $iri), $exception->getCode(), $exception);
5959
}
6060

61-
if (!isset($parameters['_resource_class']) || !isset($parameters['id'])) {
61+
if (!isset($parameters['_api_resource_class']) || !isset($parameters['id'])) {
6262
throw new InvalidArgumentException(sprintf('No resource associated to "%s".', $iri));
6363
}
6464

65-
if ($item = $this->itemDataProvider->getItem($parameters['_resource_class'], $parameters['id'], null, $fetchData)) {
65+
if ($item = $this->itemDataProvider->getItem($parameters['_api_resource_class'], $parameters['id'], null, $fetchData)) {
6666
return $item;
6767
}
6868

@@ -175,8 +175,8 @@ private function getRouteName(string $resourceClass, bool $collection) : string
175175
$operationType = $collection ? 'collection' : 'item';
176176

177177
foreach ($this->router->getRouteCollection()->all() as $routeName => $route) {
178-
$currentResourceClass = $route->getDefault('_resource_class');
179-
$operation = $route->getDefault(sprintf('_%s_operation_name', $operationType));
178+
$currentResourceClass = $route->getDefault('_api_resource_class');
179+
$operation = $route->getDefault(sprintf('_api_%s_operation_name', $operationType));
180180
$methods = $route->getMethods();
181181

182182
if ($resourceClass === $currentResourceClass && null !== $operation && (empty($methods) || in_array('GET', $methods))) {

src/Bridge/Symfony/Routing/OperationMethodResolver.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,10 @@ private function getOperationMethod(string $resourceClass, string $operationName
127127
*/
128128
private function getOperationRoute(string $resourceClass, string $operationName, bool $collection) : Route
129129
{
130-
$operationNameKey = sprintf('_%s_operation_name', $collection ? 'collection' : 'item');
130+
$operationNameKey = sprintf('_api_%s_operation_name', $collection ? 'collection' : 'item');
131131

132132
foreach ($this->router->getRouteCollection()->all() as $routeName => $route) {
133-
$currentResourceClass = $route->getDefault('_resource_class');
133+
$currentResourceClass = $route->getDefault('_api_resource_class');
134134
$currentOperationName = $route->getDefault($operationNameKey);
135135

136136
if ($resourceClass === $currentResourceClass && $operationName === $currentOperationName) {

src/Bridge/Symfony/Validator/EventListener/ValidatorViewListener.php

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111

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

14+
use ApiPlatform\Core\Api\RequestAttributesExtractor;
1415
use ApiPlatform\Core\Bridge\Symfony\Validator\Exception\ValidationException;
16+
use ApiPlatform\Core\Exception\RuntimeException;
1517
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
1618
use Symfony\Component\HttpFoundation\Request;
1719
use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
@@ -44,26 +46,24 @@ public function onKernelView(GetResponseForControllerResultEvent $event)
4446
{
4547
$request = $event->getRequest();
4648

47-
$resourceClass = $request->attributes->get('_resource_class');
48-
$itemOperationName = $request->attributes->get('_item_operation_name');
49-
$collectionOperationName = $request->attributes->get('_collection_operation_name');
49+
try {
50+
$attributes = RequestAttributesExtractor::extractAttributes($request);
51+
} catch (RuntimeException $e) {
52+
return;
53+
}
5054

51-
$method = $request->getMethod();
52-
if (
53-
!$resourceClass || (!$itemOperationName && !$collectionOperationName) ||
54-
(Request::METHOD_POST !== $method && Request::METHOD_PUT !== $method && Request::METHOD_PATCH !== $method)
55-
) {
55+
if (!in_array($request->getMethod(), [Request::METHOD_POST, Request::METHOD_PUT, Request::METHOD_PATCH], true)) {
5656
return;
5757
}
5858

5959
$data = $event->getControllerResult();
6060

61-
$resourceMetadata = $this->resourceMetadataFactory->create($resourceClass);
61+
$resourceMetadata = $this->resourceMetadataFactory->create($attributes['resource_class']);
6262

63-
if ($collectionOperationName) {
64-
$validationGroups = $resourceMetadata->getCollectionOperationAttribute($collectionOperationName, 'validation_groups');
63+
if (isset($attributes['collection_operation_name'])) {
64+
$validationGroups = $resourceMetadata->getCollectionOperationAttribute($attributes['collection_operation_name'], 'validation_groups');
6565
} else {
66-
$validationGroups = $resourceMetadata->getItemOperationAttribute($itemOperationName, 'validation_groups');
66+
$validationGroups = $resourceMetadata->getItemOperationAttribute($attributes['item_operation_name'], 'validation_groups');
6767
}
6868

6969
if (!$validationGroups) {

src/EventListener/DeserializerViewListener.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,18 +50,18 @@ public function onKernelView(GetResponseForControllerResultEvent $event)
5050
}
5151

5252
try {
53-
$extractedAttributes = RequestAttributesExtractor::extractAttributes($request);
53+
$attributes = RequestAttributesExtractor::extractAttributes($request);
5454
} catch (RuntimeException $e) {
5555
return;
5656
}
5757

58-
$context = $this->serializerContextBuilder->createFromRequest($request, false, $extractedAttributes);
58+
$context = $this->serializerContextBuilder->createFromRequest($request, false, $attributes);
5959
if (null !== $controllerResult) {
6060
$context['object_to_populate'] = $controllerResult;
6161
}
6262

6363
$event->setControllerResult(
64-
$this->serializer->deserialize($request->getContent(), $extractedAttributes[0], $extractedAttributes[3], $context)
64+
$this->serializer->deserialize($request->getContent(), $attributes['resource_class'], $attributes['format'], $context)
6565
);
6666
}
6767
}

src/EventListener/FormatRequestListener.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public function __construct(Negotiator $negotiator, array $formats)
3636
public function onKernelRequest(GetResponseEvent $event)
3737
{
3838
$request = $event->getRequest();
39-
if (!$request->attributes->get('_resource_class')) {
39+
if (null === $request->attributes->get('_api_resource_class')) {
4040
return;
4141
}
4242

0 commit comments

Comments
 (0)