Bez popisu

ReflectionContainer.php 3.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. <?php declare(strict_types=1);
  2. namespace Automattic\WooCommerce\Vendor\League\Container;
  3. use Automattic\WooCommerce\Vendor\League\Container\Argument\{ArgumentResolverInterface, ArgumentResolverTrait};
  4. use Automattic\WooCommerce\Vendor\League\Container\Exception\NotFoundException;
  5. use Psr\Container\ContainerInterface;
  6. use ReflectionClass;
  7. use ReflectionException;
  8. use ReflectionFunction;
  9. use ReflectionMethod;
  10. class ReflectionContainer implements ArgumentResolverInterface, ContainerInterface
  11. {
  12. use ArgumentResolverTrait;
  13. use ContainerAwareTrait;
  14. /**
  15. * @var boolean
  16. */
  17. protected $cacheResolutions = false;
  18. /**
  19. * Cache of resolutions.
  20. *
  21. * @var array
  22. */
  23. protected $cache = [];
  24. /**
  25. * {@inheritdoc}
  26. *
  27. * @throws ReflectionException
  28. */
  29. public function get($id, array $args = [])
  30. {
  31. if ($this->cacheResolutions === true && array_key_exists($id, $this->cache)) {
  32. return $this->cache[$id];
  33. }
  34. if (! $this->has($id)) {
  35. throw new NotFoundException(
  36. sprintf('Alias (%s) is not an existing class and therefore cannot be resolved', $id)
  37. );
  38. }
  39. $reflector = new ReflectionClass($id);
  40. $construct = $reflector->getConstructor();
  41. $resolution = $construct === null
  42. ? new $id
  43. : $resolution = $reflector->newInstanceArgs($this->reflectArguments($construct, $args))
  44. ;
  45. if ($this->cacheResolutions === true) {
  46. $this->cache[$id] = $resolution;
  47. }
  48. return $resolution;
  49. }
  50. /**
  51. * {@inheritdoc}
  52. */
  53. public function has($id) : bool
  54. {
  55. return class_exists($id);
  56. }
  57. /**
  58. * Invoke a callable via the container.
  59. *
  60. * @param callable $callable
  61. * @param array $args
  62. *
  63. * @return mixed
  64. *
  65. * @throws ReflectionException
  66. */
  67. public function call(callable $callable, array $args = [])
  68. {
  69. if (is_string($callable) && strpos($callable, '::') !== false) {
  70. $callable = explode('::', $callable);
  71. }
  72. if (is_array($callable)) {
  73. if (is_string($callable[0])) {
  74. $callable[0] = $this->getContainer()->get($callable[0]);
  75. }
  76. $reflection = new ReflectionMethod($callable[0], $callable[1]);
  77. if ($reflection->isStatic()) {
  78. $callable[0] = null;
  79. }
  80. return $reflection->invokeArgs($callable[0], $this->reflectArguments($reflection, $args));
  81. }
  82. if (is_object($callable)) {
  83. $reflection = new ReflectionMethod($callable, '__invoke');
  84. return $reflection->invokeArgs($callable, $this->reflectArguments($reflection, $args));
  85. }
  86. $reflection = new ReflectionFunction(\Closure::fromCallable($callable));
  87. return $reflection->invokeArgs($this->reflectArguments($reflection, $args));
  88. }
  89. /**
  90. * Whether the container should default to caching resolutions and returning
  91. * the cache on following calls.
  92. *
  93. * @param boolean $option
  94. *
  95. * @return self
  96. */
  97. public function cacheResolutions(bool $option = true) : ContainerInterface
  98. {
  99. $this->cacheResolutions = $option;
  100. return $this;
  101. }
  102. }