15 private $configuration = [];
17 private static $globalAutoWiredParameters;
19 private $autoWiredParameters = [];
21 private $reflectionFunctionAbstract;
23 private $methodParams =
null;
27 public function __construct($instance, $method, $configuration = [])
29 $this->instance = $instance;
30 $this->method = $method;
31 $this->configuration = $configuration;
33 if ($this->instance ===
null)
35 $this->buildReflectionFunction();
39 $this->buildReflectionMethod();
46 return new static(
null, $callable, $configuration);
49 final public static function buildForMethod($instance, $method, $configuration = [])
51 return new static($instance, $method, $configuration);
54 private function buildReflectionMethod()
56 $this->reflectionFunctionAbstract = new \ReflectionMethod($this->instance, $this->method);
57 $this->reflectionFunctionAbstract->setAccessible(
true);
60 private function buildReflectionFunction()
62 $this->reflectionFunctionAbstract = new \ReflectionFunction($this->method);
70 return $this->instance;
86 return $this->configuration;
96 $this->configuration = $configuration;
108 $this->autoWiredParameters = [];
110 foreach ($parameters as $parameter)
120 $this->autoWiredParameters[] = $parameter;
132 if (self::$globalAutoWiredParameters ===
null)
134 self::$globalAutoWiredParameters = new \SplObjectStorage();
137 if (!self::$globalAutoWiredParameters->contains($parameter))
139 self::$globalAutoWiredParameters[$parameter] = $parameter;
149 if (self::$globalAutoWiredParameters ===
null)
154 if (self::$globalAutoWiredParameters->contains($parameter))
156 self::$globalAutoWiredParameters->detach($parameter);
160 private function getPriorityByParameter(
Parameter $parameter)
170 return $this->autoWiredParameters;
175 $this->configuration[
'sourceParameters'] = $parameters;
182 return $this->configuration[
'sourceParameters']?: [];
187 if (!isset($this->configuration[
'sourceParameters']))
189 $this->configuration[
'sourceParameters'] = [];
192 $this->configuration[
'sourceParameters'][] = $parameter;
205 if ($this->reflectionFunctionAbstract instanceof \ReflectionMethod)
207 return $this->reflectionFunctionAbstract->invokeArgs($this->instance, $this->
getArgs());
210 if ($this->reflectionFunctionAbstract instanceof \ReflectionFunction)
212 return $this->reflectionFunctionAbstract->invokeArgs($this->
getArgs());
215 catch (\TypeError $exception)
220 catch (\ErrorException $exception)
235 if ($this->methodParams ===
null)
240 return $this->methodParams;
251 $this->methodParams = $params;
252 $this->args = array_values($params);
263 if ($this->args ===
null)
271 private function bindParams()
273 $this->args = $this->methodParams = [];
275 foreach ($this->reflectionFunctionAbstract->getParameters() as $param)
277 $value = $this->getParameterValue($param);
278 $this->args[] = $this->methodParams[$param->getName()] = $value;
289 private function getAutoWiredByClass(\ReflectionParameter $reflectionParameter)
291 $result = new \SplPriorityQueue();
292 foreach ($this->getAllAutoWiredParameters() as $parameter)
294 if ($parameter->match($reflectionParameter))
296 $result->insert($parameter, $this->getPriorityByParameter($parameter));
306 private function getAllAutoWiredParameters()
309 if (self::$globalAutoWiredParameters)
311 foreach (self::$globalAutoWiredParameters as $globalAutoWiredParameter)
313 $list[] = $globalAutoWiredParameter;
324 $constructedValue = $autoWireParameter->
constructValue($parameter, $captureResult);
327 'value' => $constructedValue,
333 private function getParameterValue(\ReflectionParameter $parameter)
337 $reflectionType = $parameter->getType();
339 ($reflectionType instanceof \ReflectionUnionType)
340 || ($reflectionType instanceof \ReflectionIntersectionType)
344 "Currently there is no support for union or intersection types {{$parameter->getName()}}",
349 if (($reflectionType instanceof \ReflectionNamedType) && !$reflectionType->isBuiltin())
351 foreach ($this->getAutoWiredByClass($parameter) as $autoWireParameter)
353 $result = $autoWireParameter->captureData($parameter, $sourceParameters, $this->getAllAutoWiredParameters());
354 if (!$result->isSuccess())
359 $constructedValue =
null;
360 $constructResult = $this->
constructValue($parameter, $autoWireParameter, $result);
361 if ($constructResult->isSuccess())
363 [
'value' => $constructedValue] = $constructResult->getData();
366 if ($constructedValue ===
null)
368 if ($parameter->allowsNull())
373 if ($parameter->isDefaultValueAvailable())
375 return $parameter->getDefaultValue();
378 throw new BinderArgumentException(
379 "Could not construct parameter {{$parameter->getName()}}",
381 $constructResult->getErrors(),
385 return $constructedValue;
388 if ($parameter->isDefaultValueAvailable())
390 return $parameter->getDefaultValue();
393 $exceptionMessage =
"Could not find value for parameter to build auto wired argument {{$reflectionType->getName()} \${$parameter->getName()}}";
394 if (isset($result) && ($result instanceof Result) && $result->getErrorMessages())
396 $exceptionMessage = $result->getErrorMessages()[0];
399 throw new BinderArgumentException(
405 $value = $this->findParameterInSourceList($parameter->getName(), $status);
406 if ($status === self::STATUS_NOT_FOUND)
408 if ($parameter->isDefaultValueAvailable())
410 return $parameter->getDefaultValue();
413 throw new BinderArgumentException(
414 "Could not find value for parameter {{$parameter->getName()}}",
418 if ($reflectionType instanceof \ReflectionNamedType)
420 $declarationChecker =
new TypeDeclarationChecker($reflectionType, $value);
421 if (!$declarationChecker->isSatisfied())
423 throw new BinderArgumentException(
424 "Invalid value {{$value}} to match with parameter {{$parameter->getName()}}. Should be value of type {$reflectionType->getName()}.",
428 if ($declarationChecker->isArray())
430 $value = (array)$value;
437 private function findParameterInSourceList($name, &$status)
442 if (isset($source[$name]))
444 return $source[$name];
447 if ($source instanceof \ArrayAccess && $source->offsetExists($name))
449 return $source[$name];
452 if (is_array($source) && array_key_exists($name, $source))
454 return $source[$name];
static unRegisterGlobalAutoWiredParameter(Parameter $parameter)
appendSourcesParametersToMap(array $parameter)
appendAutoWiredParameter(Parameter $parameter)
static registerGlobalAutoWiredParameter(Parameter $parameter)
__construct($instance, $method, $configuration=[])
static buildForFunction($callable, $configuration=[])
setAutoWiredParameters(array $parameters)
static buildForMethod($instance, $method, $configuration=[])
setSourcesParametersToMap(array $parameters)
constructValue(\ReflectionParameter $parameter, Parameter $autoWireParameter, Result $captureResult)
constructValue(\ReflectionParameter $parameter, Result $captureResult, $newThis=null)