123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- <?php
- namespace Drupal\Component\Utility;
- /**
- * Resolves the arguments to pass to a callable.
- */
- class ArgumentsResolver implements ArgumentsResolverInterface {
- /**
- * An associative array of parameter names to scalar candidate values.
- *
- * @var array
- */
- protected $scalars;
- /**
- * An associative array of parameter names to object candidate values.
- *
- * @var array
- */
- protected $objects;
- /**
- * An array object candidates tried on every parameter regardless of name.
- *
- * @var array
- */
- protected $wildcards;
- /**
- * Constructs a new ArgumentsResolver.
- *
- * @param array $scalars
- * An associative array of parameter names to scalar candidate values.
- * @param object[] $objects
- * An associative array of parameter names to object candidate values.
- * @param object[] $wildcards
- * An array object candidates tried on every parameter regardless of its
- * name.
- */
- public function __construct(array $scalars, array $objects, array $wildcards) {
- $this->scalars = $scalars;
- $this->objects = $objects;
- $this->wildcards = $wildcards;
- }
- /**
- * {@inheritdoc}
- */
- public function getArguments(callable $callable) {
- $arguments = [];
- foreach ($this->getReflector($callable)->getParameters() as $parameter) {
- $arguments[] = $this->getArgument($parameter);
- }
- return $arguments;
- }
- /**
- * Gets the argument value for a parameter.
- *
- * @param \ReflectionParameter $parameter
- * The parameter of a callable to get the value for.
- *
- * @return mixed
- * The value of the requested parameter value.
- *
- * @throws \RuntimeException
- * Thrown when there is a missing parameter.
- */
- protected function getArgument(\ReflectionParameter $parameter) {
- $parameter_type_hint = $parameter->getClass();
- $parameter_name = $parameter->getName();
- // If the argument exists and is NULL, return it, regardless of
- // parameter type hint.
- if (!isset($this->objects[$parameter_name]) && array_key_exists($parameter_name, $this->objects)) {
- return NULL;
- }
- if ($parameter_type_hint) {
- // If the argument exists and complies with the type hint, return it.
- if (isset($this->objects[$parameter_name]) && is_object($this->objects[$parameter_name]) && $parameter_type_hint->isInstance($this->objects[$parameter_name])) {
- return $this->objects[$parameter_name];
- }
- // Otherwise, resolve wildcard arguments by type matching.
- foreach ($this->wildcards as $wildcard) {
- if ($parameter_type_hint->isInstance($wildcard)) {
- return $wildcard;
- }
- }
- }
- elseif (isset($this->scalars[$parameter_name])) {
- return $this->scalars[$parameter_name];
- }
- // If the callable provides a default value, use it.
- if ($parameter->isDefaultValueAvailable()) {
- return $parameter->getDefaultValue();
- }
- // Can't resolve it: call a method that throws an exception or can be
- // overridden to do something else.
- return $this->handleUnresolvedArgument($parameter);
- }
- /**
- * Gets a reflector for the access check callable.
- *
- * The access checker may be either a procedural function (in which case the
- * callable is the function name) or a method (in which case the callable is
- * an array of the object and method name).
- *
- * @param callable $callable
- * The callable (either a function or a method).
- *
- * @return \ReflectionFunctionAbstract
- * The ReflectionMethod or ReflectionFunction to introspect the callable.
- */
- protected function getReflector(callable $callable) {
- return is_array($callable) ? new \ReflectionMethod($callable[0], $callable[1]) : new \ReflectionFunction($callable);
- }
- /**
- * Handles unresolved arguments for getArgument().
- *
- * Subclasses that override this method may return a default value
- * instead of throwing an exception.
- *
- * @throws \RuntimeException
- * Thrown when there is a missing parameter.
- */
- protected function handleUnresolvedArgument(\ReflectionParameter $parameter) {
- $class = $parameter->getDeclaringClass();
- $function = $parameter->getDeclaringFunction();
- if ($class && !$function->isClosure()) {
- $function_name = $class->getName() . '::' . $function->getName();
- }
- else {
- $function_name = $function->getName();
- }
- throw new \RuntimeException(sprintf('Callable "%s" requires a value for the "$%s" argument.', $function_name, $parameter->getName()));
- }
- }
|