Namespaces

  • Latte
    • Loaders
    • Macros
    • Runtime
  • Nette
    • Application
      • Responses
      • Routers
      • UI
    • Bridges
      • ApplicationLatte
      • ApplicationTracy
      • CacheLatte
      • DatabaseDI
      • DatabaseTracy
      • DITracy
      • FormsLatte
      • Framework
      • HttpTracy
      • SecurityTracy
    • Caching
      • Storages
    • ComponentModel
    • Database
      • Drivers
      • Reflection
      • Table
    • DI
      • Config
        • Adapters
      • Extensions
    • Diagnostics
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Latte
    • Loaders
    • Localization
    • Mail
    • Neon
    • PhpGenerator
    • Reflection
    • Security
    • Templating
    • Utils
  • NetteModule
  • none
  • Tracy

Classes

  • Compiler
  • CompilerExtension
  • Container
  • ContainerBuilder
  • ContainerFactory
  • Helpers
  • ServiceDefinition
  • Statement

Exceptions

  • MissingServiceException
  • ServiceCreationException
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  • Other releases
  • Nette homepage
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (https://nette.org)
  5:  * Copyright (c) 2004 David Grudl (http://davidgrudl.com)
  6:  */
  7: 
  8: namespace Nette\DI;
  9: 
 10: use Nette;
 11: 
 12: 
 13: /**
 14:  * The DI helpers.
 15:  *
 16:  * @author     David Grudl
 17:  */
 18: class Helpers
 19: {
 20: 
 21:     /**
 22:      * Expands %placeholders%.
 23:      * @param  mixed
 24:      * @param  array
 25:      * @param  bool
 26:      * @return mixed
 27:      * @throws Nette\InvalidArgumentException
 28:      */
 29:     public static function expand($var, array $params, $recursive = FALSE)
 30:     {
 31:         if (is_array($var)) {
 32:             $res = array();
 33:             foreach ($var as $key => $val) {
 34:                 $res[$key] = self::expand($val, $params, $recursive);
 35:             }
 36:             return $res;
 37: 
 38:         } elseif ($var instanceof \stdClass || $var instanceof Statement) {
 39:             $res = clone $var;
 40:             foreach ($var as $key => $val) {
 41:                 $res->$key = self::expand($val, $params, $recursive);
 42:             }
 43:             return $res;
 44: 
 45:         } elseif (!is_string($var)) {
 46:             return $var;
 47:         }
 48: 
 49:         $parts = preg_split('#%([\w.-]*)%#i', $var, -1, PREG_SPLIT_DELIM_CAPTURE);
 50:         $res = '';
 51:         foreach ($parts as $n => $part) {
 52:             if ($n % 2 === 0) {
 53:                 $res .= $part;
 54: 
 55:             } elseif ($part === '') {
 56:                 $res .= '%';
 57: 
 58:             } elseif (isset($recursive[$part])) {
 59:                 throw new Nette\InvalidArgumentException(sprintf('Circular reference detected for variables: %s.', implode(', ', array_keys($recursive))));
 60: 
 61:             } else {
 62:                 try {
 63:                     $val = Nette\Utils\Arrays::get($params, explode('.', $part));
 64:                 } catch (Nette\InvalidArgumentException $e) {
 65:                     throw new Nette\InvalidArgumentException("Missing parameter '$part'.", 0, $e);
 66:                 }
 67:                 if ($recursive) {
 68:                     $val = self::expand($val, $params, (is_array($recursive) ? $recursive : array()) + array($part => 1));
 69:                 }
 70:                 if (strlen($part) + 2 === strlen($var)) {
 71:                     return $val;
 72:                 }
 73:                 if (!is_scalar($val)) {
 74:                     throw new Nette\InvalidArgumentException("Unable to concatenate non-scalar parameter '$part' into '$var'.");
 75:                 }
 76:                 $res .= $val;
 77:             }
 78:         }
 79:         return $res;
 80:     }
 81: 
 82: 
 83:     /**
 84:      * Generates list of arguments using autowiring.
 85:      * @param  Nette\Reflection\GlobalFunction|Nette\Reflection\Method
 86:      * @return array
 87:      */
 88:     public static function autowireArguments(\ReflectionFunctionAbstract $method, array $arguments, $container)
 89:     {
 90:         $optCount = 0;
 91:         $num = -1;
 92:         $res = array();
 93: 
 94:         foreach ($method->getParameters() as $num => $parameter) {
 95:             if (array_key_exists($num, $arguments)) {
 96:                 $res[$num] = $arguments[$num];
 97:                 unset($arguments[$num]);
 98:                 $optCount = 0;
 99: 
100:             } elseif (array_key_exists($parameter->getName(), $arguments)) {
101:                 $res[$num] = $arguments[$parameter->getName()];
102:                 unset($arguments[$parameter->getName()]);
103:                 $optCount = 0;
104: 
105:             } elseif ($class = $parameter->getClassName()) { // has object type hint
106:                 $res[$num] = $container->getByType($class, FALSE);
107:                 if ($res[$num] === NULL) {
108:                     if ($parameter->allowsNull()) {
109:                         $optCount++;
110:                     } elseif (class_exists($class) || interface_exists($class)) {
111:                         throw new ServiceCreationException("Service of type {$class} needed by $method not found. Did you register it in configuration file?");
112:                     } else {
113:                         throw new ServiceCreationException("Class {$class} needed by $method not found. Check type hint and 'use' statements.");
114:                     }
115:                 } else {
116:                     if ($container instanceof ContainerBuilder) {
117:                         $res[$num] = '@' . $res[$num];
118:                     }
119:                     $optCount = 0;
120:                 }
121: 
122:             } elseif ($parameter->isOptional()) {
123:                 // PDO::__construct has optional parameter without default value (and isArray() and allowsNull() returns FALSE)
124:                 $res[$num] = $parameter->isDefaultValueAvailable() ? $parameter->getDefaultValue() : NULL;
125:                 $optCount++;
126: 
127:             } else {
128:                 throw new ServiceCreationException("Parameter $parameter has no type hint, so its value must be specified.");
129:             }
130:         }
131: 
132:         // extra parameters
133:         while (array_key_exists(++$num, $arguments)) {
134:             $res[$num] = $arguments[$num];
135:             unset($arguments[$num]);
136:             $optCount = 0;
137:         }
138:         if ($arguments) {
139:             throw new ServiceCreationException("Unable to pass specified arguments to $method.");
140:         }
141: 
142:         return $optCount ? array_slice($res, 0, -$optCount) : $res;
143:     }
144: 
145: 
146:     /**
147:      * Generates list of properties with annotation @inject.
148:      * @return array
149:      */
150:     public static function getInjectProperties(Nette\Reflection\ClassType $class, $container = NULL)
151:     {
152:         $res = array();
153:         foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) {
154:             $type = $property->getAnnotation('var');
155:             if (!$property->getAnnotation('inject')) {
156:                 continue;
157: 
158:             } elseif (!$type) {
159:                 throw new Nette\InvalidStateException("Property $property has no @var annotation.");
160:             }
161: 
162:             $type = Nette\Reflection\AnnotationsParser::expandClassName($type, self::getDeclaringClass($property));
163:             if (!class_exists($type) && !interface_exists($type)) {
164:                 throw new Nette\InvalidStateException("Class or interface '$type' used in @var annotation at $property not found. Check annotation and 'use' statements.");
165:             } elseif ($container && !$container->getByType($type, FALSE)) {
166:                 throw new ServiceCreationException("Service of type {$type} used in @var annotation at $property not found. Did you register it in configuration file?");
167:             }
168:             $res[$property->getName()] = $type;
169:         }
170:         return $res;
171:     }
172: 
173: 
174:     /**
175:      * Returns declaring class or trait.
176:      * @return \ReflectionClass
177:      */
178:     private static function getDeclaringClass(\ReflectionProperty $prop)
179:     {
180:         if (PHP_VERSION_ID >= 50400) {
181:             foreach ($prop->getDeclaringClass()->getTraits() as $trait) {
182:                 if ($trait->hasProperty($prop->getName())) {
183:                     return self::getDeclaringClass($trait->getProperty($prop->getName()));
184:                 }
185:             }
186:         }
187:         return $prop->getDeclaringClass();
188:     }
189: 
190: }
191: 
Nette 2.2 API documentation generated by ApiGen 2.8.0