/** * Compiles an inline factory binding by creating a replacement method in the DI container. * * @param Binding $binding * @return string */ protected function compileInlineFactoryBinding(Binding $binding) { $code = ''; $num = count($this->methods); $ref = new \ReflectionFunction($binding->getTarget()); $sig = $this->generateReplacementMethodSignature($ref, $num); $body = $this->extractClosureCode($ref); $this->methods[] = "\t\t" . $sig . " {\n" . $body . "\n\t\t}"; $resolvers = (array) $binding->getResolvers(); foreach ($ref->getParameters() as $param) { if ($this->getParamType($param) === Configuration::class) { $con = "\$this->config->getConfig(" . var_export(str_replace('\\', '.', $binding->getTypeName()), true) . ')'; $resolvers[$param->name] = new CompiledCodeFragment($con); } } foreach ($ref->getParameters() as $param) { if (!$param->isOptional() && InjectionPointInterface::class === $this->getParamType($param)) { $code .= "\t\tif(\$point === NULL) {\n"; $code .= "\t\t\tthrow new ContextLookupException("; $code .= var_export(sprintf('Factory for %s requires access to an injection point', $binding->getTypeName()), true); $code .= ");\n"; $code .= "\t\t}\n"; } } $call = $this->generateCallCode($binding->getTypeName(), $ref, $num, [], $resolvers); $setterInjection = $binding->isMarked(SetterInjection::class); $initializers = (array) $binding->getInitializers(); if (empty($initializers) && !$setterInjection) { $code .= "\t\treturn \$this->initialize(" . $call . ");\n"; } else { $code .= "\t\t\$obj = \$this->initialize(" . $call . ");\n"; if ($setterInjection) { $code .= "\t\t" . $this->compileSetterInjector($binding, false) . "\n"; } foreach ($initializers as $initializer) { $num = count($this->methods); $ref = new \ReflectionFunction($initializer); $sig = $this->generateReplacementMethodSignature($ref, $num); $body = $this->extractClosureCode($ref); $this->methods[] = "\t\t" . $sig . " {\n" . $body . "\n\t\t}"; $code .= "\t\t\$obj = " . $this->generateCallCode($binding->getTypeName(), $ref, $num, ['$obj']) . " ?: \$obj;\n"; } $code .= "\t\treturn \$obj;\n"; } return $code; }