private function getParams(\ReflectionMethod $method, array $rule)
{
// Cache some information about the parameter in $paramInfo so (slow) reflection isn't needed every time
$paramInfo = [];
foreach ($method->getParameters() as $param) {
$class = $param->getClass() ? $param->getClass()->name : null;
$paramInfo[] = [$class, $param, isset($rule['substitutions']) && array_key_exists($class, $rule['substitutions'])];
}
// Return a closure that uses the cached information to generate the arguments for the method
return function (array $args, array $share = []) use($paramInfo, $rule) {
// Now merge all the possible parameters: user-defined in the rule via constructParams, shared instances and the $args argument from $dice->create();
if ($share || isset($rule['constructParams'])) {
$args = array_merge($args, isset($rule['constructParams']) ? $this->expand($rule['constructParams'], $share) : [], $share);
}
$parameters = [];
// Now find a value for each method parameter
foreach ($paramInfo as list($class, $param, $sub)) {
// First loop through $args and see whether or not each value can match the current parameter based on type hint
if ($args) {
foreach ($args as $i => $arg) {
// This if statement actually gives a ~10% speed increase when $args isn't set
if ($class && ($arg instanceof $class || $arg === null && $param->allowsNull())) {
// The argument matched, store it and remove it from $args so it won't wrongly match another parameter
$parameters[] = array_splice($args, $i, 1)[0];
// Move on to the next parameter
continue 2;
}
}
}
// When nothing from $args matches but a class is type hinted, create an instance to use, using a substitution if set
if ($class) {
$parameters[] = $sub ? $this->expand($rule['substitutions'][$class], $share, true) : $this->create($class, [], $share);
} else {
if ($param->isVariadic()) {
$parameters = array_merge($parameters, $args);
} else {
if ($args) {
$parameters[] = $this->expand(array_shift($args));
} else {
$parameters[] = $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null;
}
}
}
}
// variadic functions will only have one argument. To account for those, append any remaining arguments to the list
return $parameters;
};
}