vendor/api-platform/core/src/Api/ResourceClassResolver.php line 42

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\Api;
  12. use ApiPlatform\Exception\InvalidArgumentException;
  13. use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface;
  14. use ApiPlatform\Util\ClassInfoTrait;
  15. /**
  16. * {@inheritdoc}
  17. *
  18. * @author Kévin Dunglas <dunglas@gmail.com>
  19. * @author Samuel ROZE <samuel.roze@gmail.com>
  20. */
  21. final class ResourceClassResolver implements ResourceClassResolverInterface
  22. {
  23. use ClassInfoTrait;
  24. private $resourceNameCollectionFactory;
  25. private $localIsResourceClassCache = [];
  26. private $localMostSpecificResourceClassCache = [];
  27. public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory)
  28. {
  29. $this->resourceNameCollectionFactory = $resourceNameCollectionFactory;
  30. }
  31. /**
  32. * {@inheritdoc}
  33. */
  34. public function getResourceClass($value, string $resourceClass = null, bool $strict = false): string
  35. {
  36. if ($strict && null === $resourceClass) {
  37. throw new InvalidArgumentException('Strict checking is only possible when resource class is specified.');
  38. }
  39. $objectClass = \is_object($value) ? $this->getObjectClass($value) : null;
  40. $actualClass = ($objectClass && (!$value instanceof \Traversable || $this->isResourceClass($objectClass))) ? $this->getObjectClass($value) : null;
  41. if (null === $actualClass && null === $resourceClass) {
  42. throw new InvalidArgumentException('Resource type could not be determined. Resource class must be specified.');
  43. }
  44. if (null !== $actualClass && !$this->isResourceClass($actualClass)) {
  45. throw new InvalidArgumentException(sprintf('No resource class found for object of type "%s".', $actualClass));
  46. }
  47. if (null !== $resourceClass && !$this->isResourceClass($resourceClass)) {
  48. throw new InvalidArgumentException(sprintf('Specified class "%s" is not a resource class.', $resourceClass));
  49. }
  50. if ($strict && null !== $actualClass && !is_a($actualClass, $resourceClass, true)) {
  51. throw new InvalidArgumentException(sprintf('Object of type "%s" does not match "%s" resource class.', $actualClass, $resourceClass));
  52. }
  53. $targetClass = $actualClass ?? $resourceClass;
  54. if (isset($this->localMostSpecificResourceClassCache[$targetClass])) {
  55. return $this->localMostSpecificResourceClassCache[$targetClass];
  56. }
  57. $mostSpecificResourceClass = null;
  58. foreach ($this->resourceNameCollectionFactory->create() as $resourceClassName) {
  59. if (!is_a($targetClass, $resourceClassName, true)) {
  60. continue;
  61. }
  62. if (null === $mostSpecificResourceClass || is_subclass_of($resourceClassName, $mostSpecificResourceClass)) {
  63. $mostSpecificResourceClass = $resourceClassName;
  64. }
  65. }
  66. if (null === $mostSpecificResourceClass) {
  67. throw new \LogicException('Unexpected execution flow.');
  68. }
  69. $this->localMostSpecificResourceClassCache[$targetClass] = $mostSpecificResourceClass;
  70. return $mostSpecificResourceClass;
  71. }
  72. /**
  73. * {@inheritdoc}
  74. */
  75. public function isResourceClass(string $type): bool
  76. {
  77. if (isset($this->localIsResourceClassCache[$type])) {
  78. return $this->localIsResourceClassCache[$type];
  79. }
  80. foreach ($this->resourceNameCollectionFactory->create() as $resourceClass) {
  81. if (is_a($type, $resourceClass, true)) {
  82. return $this->localIsResourceClassCache[$type] = true;
  83. }
  84. }
  85. return $this->localIsResourceClassCache[$type] = false;
  86. }
  87. }
  88. class_alias(ResourceClassResolver::class, \ApiPlatform\Core\Api\ResourceClassResolver::class);