vendor/api-platform/core/src/Core/Metadata/Resource/Factory/ExtractorResourceMetadataFactory.php line 32

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\Metadata\Resource\Factory;
  12. use ApiPlatform\Core\Exception\ResourceClassNotFoundException;
  13. use ApiPlatform\Core\Metadata\Resource\ResourceMetadata;
  14. use ApiPlatform\Metadata\Extractor\ResourceExtractorInterface;
  15. /**
  16. * Creates resource's metadata using an extractor.
  17. *
  18. * @author Kévin Dunglas <dunglas@gmail.com>
  19. * @author Antoine Bluchet <soyuka@gmail.com>
  20. */
  21. final class ExtractorResourceMetadataFactory implements ResourceMetadataFactoryInterface
  22. {
  23. private $extractor;
  24. private $decorated;
  25. private $defaults;
  26. public function __construct(ResourceExtractorInterface $extractor, ResourceMetadataFactoryInterface $decorated = null, array $defaults = [])
  27. {
  28. $this->extractor = $extractor;
  29. $this->decorated = $decorated;
  30. $this->defaults = $defaults + ['attributes' => []];
  31. }
  32. /**
  33. * {@inheritdoc}
  34. */
  35. public function create(string $resourceClass): ResourceMetadata
  36. {
  37. $parentResourceMetadata = null;
  38. if ($this->decorated) {
  39. try {
  40. $parentResourceMetadata = $this->decorated->create($resourceClass);
  41. } catch (ResourceClassNotFoundException $resourceNotFoundException) {
  42. // Ignore not found exception from decorated factories
  43. }
  44. }
  45. if (!(class_exists($resourceClass) || interface_exists($resourceClass)) || !$resource = $this->extractor->getResources()[$resourceClass] ?? false) {
  46. return $this->handleNotFound($parentResourceMetadata, $resourceClass);
  47. }
  48. $resource['description'] = $resource['description'] ?? $this->defaults['description'] ?? null;
  49. $resource['iri'] = $resource['iri'] ?? $this->defaults['iri'] ?? null;
  50. $resource['itemOperations'] = $resource['itemOperations'] ?? $this->defaults['item_operations'] ?? null;
  51. $resource['collectionOperations'] = $resource['collectionOperations'] ?? $this->defaults['collection_operations'] ?? null;
  52. $resource['graphql'] = $resource['graphql'] ?? $this->defaults['graphql'] ?? null;
  53. if (\array_key_exists('attributes', $resource) && (null !== $resource['attributes'] || [] !== $this->defaults['attributes'])) {
  54. $resource['attributes'] = (array) $resource['attributes'];
  55. foreach ($this->defaults['attributes'] as $key => $value) {
  56. if (!isset($resource['attributes'][$key])) {
  57. $resource['attributes'][$key] = $value;
  58. }
  59. }
  60. }
  61. return $this->update($parentResourceMetadata ?: new ResourceMetadata(), $resource);
  62. }
  63. /**
  64. * Returns the metadata from the decorated factory if available or throws an exception.
  65. *
  66. * @throws ResourceClassNotFoundException
  67. */
  68. private function handleNotFound(?ResourceMetadata $parentPropertyMetadata, string $resourceClass): ResourceMetadata
  69. {
  70. if (null !== $parentPropertyMetadata) {
  71. return $parentPropertyMetadata;
  72. }
  73. throw new ResourceClassNotFoundException(sprintf('Resource "%s" not found.', $resourceClass));
  74. }
  75. /**
  76. * Creates a new instance of metadata if the property is not already set.
  77. */
  78. private function update(ResourceMetadata $resourceMetadata, array $metadata): ResourceMetadata
  79. {
  80. foreach (['shortName', 'description', 'iri', 'itemOperations', 'collectionOperations', 'subresourceOperations', 'graphql', 'attributes'] as $property) {
  81. if (!\array_key_exists($property, $metadata) || null === $metadata[$property] || null !== $resourceMetadata->{'get'.ucfirst($property)}()) {
  82. continue;
  83. }
  84. $resourceMetadata = $resourceMetadata->{'with'.ucfirst($property)}($metadata[$property]);
  85. }
  86. return $resourceMetadata;
  87. }
  88. }