/**
  * Generates list of arguments using autowiring.
  * @return array
  */
 public static function autowireArguments(\ReflectionFunctionAbstract $method, array $arguments, $container)
 {
     $optCount = 0;
     $num = -1;
     $res = array();
     $methodName = ($method instanceof \ReflectionMethod ? $method->getDeclaringClass()->getName() . '::' : '') . $method->getName() . '()';
     foreach ($method->getParameters() as $num => $parameter) {
         if (array_key_exists($num, $arguments)) {
             $res[$num] = $arguments[$num];
             unset($arguments[$num]);
             $optCount = 0;
         } elseif (array_key_exists($parameter->getName(), $arguments)) {
             $res[$num] = $arguments[$parameter->getName()];
             unset($arguments[$parameter->getName()]);
             $optCount = 0;
         } elseif (($class = PhpReflection::getParameterType($parameter)) && !PhpReflection::isBuiltinType($class)) {
             $res[$num] = $container->getByType($class, FALSE);
             if ($res[$num] === NULL) {
                 if ($parameter->allowsNull()) {
                     $optCount++;
                 } elseif (class_exists($class) || interface_exists($class)) {
                     $rc = new \ReflectionClass($class);
                     if ($class !== ($hint = $rc->getName())) {
                         throw new ServiceCreationException("Service of type {$class} needed by {$methodName} not found, did you mean {$hint}?");
                     }
                     throw new ServiceCreationException("Service of type {$class} needed by {$methodName} not found. Did you register it in configuration file?");
                 } else {
                     throw new ServiceCreationException("Class {$class} needed by {$methodName} not found. Check type hint and 'use' statements.");
                 }
             } else {
                 if ($container instanceof ContainerBuilder) {
                     $res[$num] = '@' . $res[$num];
                 }
                 $optCount = 0;
             }
         } elseif ($parameter->isOptional() || $parameter->isDefaultValueAvailable()) {
             // !optional + defaultAvailable = func($a = NULL, $b) since 5.3.17 & 5.4.7
             // optional + !defaultAvailable = i.e. Exception::__construct, mysqli::mysqli, ...
             $res[$num] = $parameter->isDefaultValueAvailable() ? $parameter->getDefaultValue() : NULL;
             $optCount++;
         } else {
             throw new ServiceCreationException("Parameter \${$parameter->getName()} in {$methodName} has no class type hint or default value, so its value must be specified.");
         }
     }
     // extra parameters
     while (array_key_exists(++$num, $arguments)) {
         $res[$num] = $arguments[$num];
         unset($arguments[$num]);
         $optCount = 0;
     }
     if ($arguments) {
         throw new ServiceCreationException("Unable to pass specified arguments to {$methodName}.");
     }
     return $optCount ? array_slice($res, 0, -$optCount) : $res;
 }
Exemple #2
0
 private static function mockInjectedProperties()
 {
     /** @var \ReflectionProperty $property */
     foreach (self::$reflectedClass->getProperties() as $property) {
         if (Nette\DI\PhpReflection::parseAnnotation($property, 'inject') !== NULL || Nette\DI\PhpReflection::parseAnnotation($property, 'autowire') !== NULL) {
             if ($mockedParameterClass = Nette\DI\PhpReflection::parseAnnotation($property, 'var')) {
                 $mockedParameterClass = Nette\DI\PhpReflection::expandClassName($mockedParameterClass, Nette\DI\PhpReflection::getDeclaringClass($property));
             }
             self::setProperty($mockedParameterClass, $property);
         }
     }
 }
Exemple #3
0
 /** @internal */
 private static function checkType($class, string $name, $type, $container)
 {
     $rc = PhpReflection::getDeclaringClass(new \ReflectionProperty($class, $name));
     $fullname = $rc->getName() . '::$' . $name;
     if (!$type) {
         throw new Nette\InvalidStateException("Property {$fullname} has no @var annotation.");
     } elseif (!class_exists($type) && !interface_exists($type)) {
         throw new Nette\InvalidStateException("Class or interface '{$type}' used in @var annotation at {$fullname} not found. Check annotation and 'use' statements.");
     } elseif (!$container->getByType($type, FALSE)) {
         throw new Nette\InvalidStateException("Service of type {$type} used in @var annotation at {$fullname} not found. Did you register it in configuration file?");
     }
 }
Exemple #4
0
 /** @return string|NULL */
 private function resolveEntityClass($entity, $recursive = [])
 {
     $entity = $this->normalizeEntity($entity instanceof Statement ? $entity->getEntity() : $entity);
     if (is_array($entity)) {
         if (($service = $this->getServiceName($entity[0])) || $entity[0] instanceof Statement) {
             $entity[0] = $this->resolveEntityClass($entity[0], $recursive);
             if (!$entity[0]) {
                 return;
             } elseif (isset($this->definitions[$service]) && $this->definitions[$service]->getImplement()) {
                 // @Implement::create
                 return $entity[1] === 'create' ? $this->resolveServiceClass($service, $recursive) : NULL;
             }
         }
         try {
             $reflection = Nette\Utils\Callback::toReflection($entity[0] === '' ? $entity[1] : $entity);
             $refClass = $reflection instanceof \ReflectionMethod ? $reflection->getDeclaringClass() : NULL;
         } catch (\ReflectionException $e) {
         }
         if (isset($e) || $refClass && (!$reflection->isPublic() || $refClass->isTrait() && !$reflection->isStatic())) {
             $name = array_slice(array_keys($recursive), -1);
             throw new ServiceCreationException(sprintf("Factory '%s' used in service '%s' is not callable.", Nette\Utils\Callback::toString($entity), $name[0]));
         }
         return PhpReflection::getReturnType($reflection);
     } elseif ($service = $this->getServiceName($entity)) {
         // alias or factory
         if (Strings::contains($service, '\\')) {
             // @\Class
             return ltrim($service, '\\');
         }
         return $this->definitions[$service]->getImplement() ?: $this->resolveServiceClass($service, $recursive);
     } elseif (is_string($entity)) {
         if (!class_exists($entity) || !(new ReflectionClass($entity))->isInstantiable()) {
             $name = array_slice(array_keys($recursive), -1);
             throw new ServiceCreationException("Class {$entity} used in service '{$name['0']}' not found or is not instantiable.");
         }
         return ltrim($entity, '\\');
     }
 }
Exemple #5
0
 /**
  * Generates list of properties with annotation @inject.
  * @return array
  */
 public static function getInjectProperties(\ReflectionClass $class, $container = NULL)
 {
     $res = array();
     foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) {
         $type = PhpReflection::parseAnnotation($property, 'var');
         if (PhpReflection::parseAnnotation($property, 'inject') === NULL) {
             continue;
         } elseif (!$type) {
             throw new Nette\InvalidStateException("Property {$property} has no @var annotation.");
         }
         $type = PhpReflection::expandClassName($type, PhpReflection::getDeclaringClass($property));
         if (!class_exists($type) && !interface_exists($type)) {
             throw new Nette\InvalidStateException("Class or interface '{$type}' used in @var annotation at {$property} not found. Check annotation and 'use' statements.");
         } elseif ($container && !$container->getByType($type, FALSE)) {
             throw new ServiceCreationException("Service of type {$type} used in @var annotation at {$property} not found. Did you register it in configuration file?");
         }
         $res[$property->getName()] = $type;
     }
     return $res;
 }
Exemple #6
0
 /** privates */
 private function autowireProps()
 {
     $rc = $this->getReflection();
     foreach ($rc->getProperties() as $property) {
         $annotation = $property->getAnnotation('prop');
         if ($annotation) {
             $type = (string) $property->getAnnotation('var');
             $propName = isset($annotation['name']) ? $annotation['name'] : $property->name;
             //todo: implement @prop(type=specifictype)
             $value = $this->props->get($propName);
             if (in_array($type, ['array', 'int', 'numeric', 'string'])) {
                 if (!Validators::is($value, $type)) {
                     throw new PropValidationException("Prop {$propName} is not of required type {$type}but " . $this->getObjectType($value));
                 }
             } else {
                 $type = PhpReflection::expandClassName($type, $rc);
                 if (!$value instanceof $type) {
                     throw new PropValidationException("Prop {$propName} is not of required type {$type}, but " . $this->getObjectType($value));
                 }
             }
             $this->{$property->name} = $value;
         }
     }
 }
Exemple #7
0
 private static function hashParameters(\ReflectionFunctionAbstract $method)
 {
     $res = [];
     if (PHP_VERSION_ID < 70000 && $method->getNumberOfParameters() && $method->getFileName()) {
         $res[] = file($method->getFileName())[$method->getStartLine() - 1];
     }
     foreach ($method->getParameters() as $param) {
         $res[] = [$param->getName(), PHP_VERSION_ID >= 70000 ? PhpReflection::getParameterType($param) : NULL, $param->isVariadic(), $param->isDefaultValueAvailable() ? $param->isDefaultValueConstant() ? $param->getDefaultValueConstantName() : [$param->getDefaultValue()] : NULL];
     }
     return $res;
 }