Example #1
0
 /**
  * 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;
 }
Example #2
0
 /**
  * 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;
 }