/** * Create an object using the factory defined in the given binding. * * @param Binding $binding * @param InjectionPointInterface $point * @return object */ protected function createObjectUsingFactory(Binding $binding, InjectionPointInterface $point = NULL) { $callback = $binding->getTarget(); if (is_array($callback)) { $callback = [$this->get($callback[0]), $callback[1]]; $ref = new \ReflectionMethod(get_class($callback[0]), $callback[1]); } else { $ref = new \ReflectionFunction($callback); } $resolvers = (array) $binding->getResolvers(); // Special case: inject config of the type to be created into the factory: foreach ($ref->getParameters() as $param) { if ($this->getParamType($param) === Configuration::class) { $resolvers[$param->name] = $this->config->getConfig(str_replace('\\', '.', $binding->getTypeName())); } } $args = $this->populateArguments($ref, 0, $resolvers, $point); switch (count($args)) { case 0: $object = $callback(); break; case 1: $object = $callback($args[0]); break; case 2: $object = $callback($args[0], $args[1]); break; case 3: $object = $callback($args[0], $args[1], $args[2]); break; case 4: $object = $callback($args[0], $args[1], $args[2], $args[3]); break; default: $object = call_user_func_array($callback, $args); } if ($object instanceof ScopedProxyInterface) { return $object; } $object = $this->initialize($object); foreach ($binding->getMarkers(SetterInjection::class) as $setter) { $this->performSetterInjection($object, $setter); } $initializers = $binding->getInitializers(); if (!empty($initializers)) { $object = $this->invokeBindingInitializers($binding->getTypeName(), $object, $initializers); } return $object; }
/** * Compile a setter injector for a binding. * * @param Binding $binding * @param boolean $wrapClosure * @return string */ protected function compileSetterInjector(Binding $binding, $wrapClosure = true) { $setters = $binding->getMarkers(SetterInjection::class); if (empty($setters)) { return 'NULL'; } $setterTypeName = $binding->isImplementationBinding() ? $binding->getTarget() : $binding->getTypeName(); $code = $wrapClosure ? 'function($obj) { ' : ''; $ref = new \ReflectionClass($setterTypeName); foreach ($setters as $setter) { foreach ($this->collectSetterMethods($ref, $setter) as $method) { $params = $method->getParameters(); if (empty($params)) { continue; } $injector = '$obj->' . $method->getName() . '('; foreach ($params as $i => $param) { if (NULL === ($paramTypeName = $param->getClass())) { continue 2; } if ($i != 0) { $injector .= ', '; } $nullable = $param->isOptional() ? 'Nullable' : ''; $injector .= '$this->get' . $nullable . '(' . var_export($paramTypeName->name, true) . ', new InjectionPoint('; $injector .= 'get_class($obj), ' . var_export($method->getName(), true) . '))'; } $code .= $injector . '); '; } } return $wrapClosure ? $code . '}' : $code; }