vendor/api-platform/core/src/Core/Bridge/Symfony/Bundle/DataCollector/RequestDataCollector.php line 55

Open in your IDE?
  1. <?php
  2. /*
  3. * This file is part of the API Platform project.
  4. *
  5. * (c) Kévin Dunglas <dunglas@gmail.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. declare(strict_types=1);
  11. namespace ApiPlatform\Core\Bridge\Symfony\Bundle\DataCollector;
  12. use ApiPlatform\Core\Bridge\Symfony\Bundle\DataPersister\TraceableChainDataPersister;
  13. use ApiPlatform\Core\Bridge\Symfony\Bundle\DataProvider\TraceableChainCollectionDataProvider;
  14. use ApiPlatform\Core\Bridge\Symfony\Bundle\DataProvider\TraceableChainItemDataProvider;
  15. use ApiPlatform\Core\Bridge\Symfony\Bundle\DataProvider\TraceableChainSubresourceDataProvider;
  16. use ApiPlatform\Core\DataPersister\DataPersisterInterface;
  17. use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface;
  18. use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
  19. use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface;
  20. use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
  21. use ApiPlatform\Core\Util\RequestAttributesExtractor;
  22. use PackageVersions\Versions;
  23. use Psr\Container\ContainerInterface;
  24. use Symfony\Component\HttpFoundation\Request;
  25. use Symfony\Component\HttpFoundation\Response;
  26. use Symfony\Component\HttpKernel\DataCollector\DataCollector;
  27. /**
  28. * @author Julien DENIAU <julien.deniau@gmail.com>
  29. * @author Anthony GRASSIOT <antograssiot@free.fr>
  30. */
  31. final class RequestDataCollector extends DataCollector
  32. {
  33. private $metadataFactory;
  34. private $filterLocator;
  35. private $collectionDataProvider;
  36. private $itemDataProvider;
  37. private $subresourceDataProvider;
  38. private $dataPersister;
  39. public function __construct(ResourceMetadataFactoryInterface $metadataFactory, ContainerInterface $filterLocator, CollectionDataProviderInterface $collectionDataProvider = null, ItemDataProviderInterface $itemDataProvider = null, SubresourceDataProviderInterface $subresourceDataProvider = null, DataPersisterInterface $dataPersister = null)
  40. {
  41. $this->metadataFactory = $metadataFactory;
  42. $this->filterLocator = $filterLocator;
  43. $this->collectionDataProvider = $collectionDataProvider;
  44. $this->itemDataProvider = $itemDataProvider;
  45. $this->subresourceDataProvider = $subresourceDataProvider;
  46. $this->dataPersister = $dataPersister;
  47. }
  48. public function collect(Request $request, Response $response, \Throwable $exception = null)
  49. {
  50. $counters = ['ignored_filters' => 0];
  51. $resourceClass = $request->attributes->get('_api_resource_class');
  52. $resourceMetadata = $resourceClass ? $this->metadataFactory->create($resourceClass) : null;
  53. $filters = [];
  54. foreach ($resourceMetadata ? $resourceMetadata->getAttribute('filters', []) : [] as $id) {
  55. if ($this->filterLocator->has($id)) {
  56. $filters[$id] = \get_class($this->filterLocator->get($id));
  57. continue;
  58. }
  59. $filters[$id] = null;
  60. ++$counters['ignored_filters'];
  61. }
  62. $requestAttributes = RequestAttributesExtractor::extractAttributes($request);
  63. if (isset($requestAttributes['previous_data'])) {
  64. $requestAttributes['previous_data'] = $this->cloneVar($requestAttributes['previous_data']);
  65. }
  66. $this->data = [
  67. 'resource_class' => $resourceClass,
  68. 'resource_metadata' => $resourceMetadata ? $this->cloneVar($resourceMetadata) : null,
  69. 'acceptable_content_types' => $request->getAcceptableContentTypes(),
  70. 'filters' => $filters,
  71. 'counters' => $counters,
  72. 'dataProviders' => [],
  73. 'dataPersisters' => ['responses' => []],
  74. 'request_attributes' => $requestAttributes,
  75. ];
  76. if ($this->collectionDataProvider instanceof TraceableChainCollectionDataProvider) {
  77. $this->data['dataProviders']['collection'] = [
  78. 'context' => $this->cloneVar($this->collectionDataProvider->getContext()),
  79. 'responses' => $this->collectionDataProvider->getProvidersResponse(),
  80. ];
  81. }
  82. if ($this->itemDataProvider instanceof TraceableChainItemDataProvider) {
  83. $this->data['dataProviders']['item'] = [
  84. 'context' => $this->cloneVar($this->itemDataProvider->getContext()),
  85. 'responses' => $this->itemDataProvider->getProvidersResponse(),
  86. ];
  87. }
  88. if ($this->subresourceDataProvider instanceof TraceableChainSubresourceDataProvider) {
  89. $this->data['dataProviders']['subresource'] = [
  90. 'context' => $this->cloneVar($this->subresourceDataProvider->getContext()),
  91. 'responses' => $this->subresourceDataProvider->getProvidersResponse(),
  92. ];
  93. }
  94. if ($this->dataPersister instanceof TraceableChainDataPersister) {
  95. $this->data['dataPersisters']['responses'] = $this->dataPersister->getPersistersResponse();
  96. }
  97. }
  98. public function getAcceptableContentTypes(): array
  99. {
  100. return $this->data['acceptable_content_types'] ?? [];
  101. }
  102. public function getResourceClass()
  103. {
  104. return $this->data['resource_class'] ?? null;
  105. }
  106. public function getResourceMetadata()
  107. {
  108. return $this->data['resource_metadata'] ?? null;
  109. }
  110. public function getRequestAttributes(): array
  111. {
  112. return $this->data['request_attributes'] ?? [];
  113. }
  114. public function getFilters(): array
  115. {
  116. return $this->data['filters'] ?? [];
  117. }
  118. public function getCounters(): array
  119. {
  120. return $this->data['counters'] ?? [];
  121. }
  122. public function getCollectionDataProviders(): array
  123. {
  124. return $this->data['dataProviders']['collection'] ?? ['context' => [], 'responses' => []];
  125. }
  126. public function getItemDataProviders(): array
  127. {
  128. return $this->data['dataProviders']['item'] ?? ['context' => [], 'responses' => []];
  129. }
  130. public function getSubresourceDataProviders(): array
  131. {
  132. return $this->data['dataProviders']['subresource'] ?? ['context' => [], 'responses' => []];
  133. }
  134. public function getDataPersisters(): array
  135. {
  136. return $this->data['dataPersisters'] ?? ['responses' => []];
  137. }
  138. public function getVersion(): ?string
  139. {
  140. if (!class_exists(Versions::class)) {
  141. return null;
  142. }
  143. $version = Versions::getVersion('api-platform/core');
  144. preg_match('/^v(.*?)@/', $version, $output);
  145. return $output[1] ?? strtok($version, '@');
  146. }
  147. public function getName(): string
  148. {
  149. return 'api_platform.data_collector.request';
  150. }
  151. public function reset()
  152. {
  153. $this->data = [];
  154. }
  155. }