Namespaces

  • Latte
    • Loaders
    • Macros
    • Runtime
  • Nette
    • Application
      • Responses
      • Routers
      • UI
    • Bridges
      • ApplicationDI
      • ApplicationLatte
      • ApplicationTracy
      • CacheDI
      • CacheLatte
      • DatabaseDI
      • DatabaseTracy
      • DITracy
      • FormsDI
      • FormsLatte
      • Framework
      • HttpDI
      • HttpTracy
      • MailDI
      • ReflectionDI
      • SecurityDI
      • SecurityTracy
    • Caching
      • Storages
    • ComponentModel
    • Database
      • Conventions
      • Drivers
      • Table
    • DI
      • Config
        • Adapters
      • Extensions
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Loaders
    • Localization
    • Mail
    • Neon
    • PhpGenerator
      • Traits
    • Reflection
    • Security
    • Tokenizer
    • Utils
  • Tracy
    • Bridges
      • Nette
  • none

Classes

  • Compiler
  • CompilerExtension
  • Container
  • ContainerBuilder
  • ContainerLoader
  • DependencyChecker
  • Helpers
  • PhpGenerator
  • PhpReflection
  • ServiceDefinition
  • Statement

Exceptions

  • MissingServiceException
  • ServiceCreationException
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (https://nette.org)
  5:  * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
  6:  */
  7: 
  8: namespace Nette\DI;
  9: 
 10: use Nette;
 11: use Nette\PhpGenerator\PhpLiteral;
 12: use Nette\Utils\Reflection;
 13: 
 14: 
 15: /**
 16:  * The DI helpers.
 17:  * @internal
 18:  */
 19: class Helpers
 20: {
 21:     use Nette\StaticClass;
 22: 
 23:     /**
 24:      * Expands %placeholders%.
 25:      * @param  mixed
 26:      * @param  array
 27:      * @param  bool|array
 28:      * @return mixed
 29:      * @throws Nette\InvalidArgumentException
 30:      */
 31:     public static function expand($var, array $params, $recursive = false)
 32:     {
 33:         if (is_array($var)) {
 34:             $res = [];
 35:             foreach ($var as $key => $val) {
 36:                 $res[$key] = self::expand($val, $params, $recursive);
 37:             }
 38:             return $res;
 39: 
 40:         } elseif ($var instanceof Statement) {
 41:             return new Statement(self::expand($var->getEntity(), $params, $recursive), self::expand($var->arguments, $params, $recursive));
 42: 
 43:         } elseif (!is_string($var)) {
 44:             return $var;
 45:         }
 46: 
 47:         $parts = preg_split('#%([\w.-]*)%#i', $var, -1, PREG_SPLIT_DELIM_CAPTURE);
 48:         $res = [];
 49:         $php = false;
 50:         foreach ($parts as $n => $part) {
 51:             if ($n % 2 === 0) {
 52:                 $res[] = $part;
 53: 
 54:             } elseif ($part === '') {
 55:                 $res[] = '%';
 56: 
 57:             } elseif (isset($recursive[$part])) {
 58:                 throw new Nette\InvalidArgumentException(sprintf('Circular reference detected for variables: %s.', implode(', ', array_keys($recursive))));
 59: 
 60:             } else {
 61:                 try {
 62:                     $val = Nette\Utils\Arrays::get($params, explode('.', $part));
 63:                 } catch (Nette\InvalidArgumentException $e) {
 64:                     throw new Nette\InvalidArgumentException("Missing parameter '$part'.", 0, $e);
 65:                 }
 66:                 if ($recursive) {
 67:                     $val = self::expand($val, $params, (is_array($recursive) ? $recursive : []) + [$part => 1]);
 68:                 }
 69:                 if (strlen($part) + 2 === strlen($var)) {
 70:                     return $val;
 71:                 }
 72:                 if ($val instanceof PhpLiteral) {
 73:                     $php = true;
 74:                 } elseif (!is_scalar($val)) {
 75:                     throw new Nette\InvalidArgumentException("Unable to concatenate non-scalar parameter '$part' into '$var'.");
 76:                 }
 77:                 $res[] = $val;
 78:             }
 79:         }
 80:         if ($php) {
 81:             $res = array_filter($res, function ($val) { return $val !== ''; });
 82:             $res = array_map(function ($val) { return $val instanceof PhpLiteral ? "($val)" : var_export((string) $val, true); }, $res);
 83:             return new PhpLiteral(implode(' . ', $res));
 84:         }
 85:         return implode('', $res);
 86:     }
 87: 
 88: 
 89:     /**
 90:      * Generates list of arguments using autowiring.
 91:      * @return array
 92:      * @throws ServiceCreationException
 93:      */
 94:     public static function autowireArguments(\ReflectionFunctionAbstract $method, array $arguments, $container)
 95:     {
 96:         $optCount = 0;
 97:         $num = -1;
 98:         $res = [];
 99:         $methodName = Reflection::toString($method) . '()';
100: 
101:         foreach ($method->getParameters() as $num => $parameter) {
102:             $paramName = $parameter->getName();
103:             if (!$parameter->isVariadic() && array_key_exists($paramName, $arguments)) {
104:                 $res[$num] = $arguments[$paramName];
105:                 unset($arguments[$paramName], $arguments[$num]);
106:                 $optCount = 0;
107: 
108:             } elseif (array_key_exists($num, $arguments)) {
109:                 $res[$num] = $arguments[$num];
110:                 unset($arguments[$num]);
111:                 $optCount = 0;
112: 
113:             } elseif (($type = Reflection::getParameterType($parameter)) && !Reflection::isBuiltinType($type)) {
114:                 try {
115:                     $res[$num] = $container->getByType($type, false);
116:                 } catch (ServiceCreationException $e) {
117:                     throw new ServiceCreationException("{$e->getMessage()} (needed by $$paramName in $methodName)", 0, $e);
118:                 }
119:                 if ($res[$num] === null) {
120:                     if ($parameter->allowsNull()) {
121:                         $optCount++;
122:                     } elseif (class_exists($type) || interface_exists($type)) {
123:                         throw new ServiceCreationException("Service of type $type needed by $$paramName in $methodName not found. Did you register it in configuration file?");
124:                     } else {
125:                         throw new ServiceCreationException("Class $type needed by $$paramName in $methodName not found. Check type hint and 'use' statements.");
126:                     }
127:                 } else {
128:                     if ($container instanceof ContainerBuilder) {
129:                         $res[$num] = '@' . $res[$num];
130:                     }
131:                     $optCount = 0;
132:                 }
133: 
134:             } elseif (($type && $parameter->allowsNull()) || $parameter->isOptional() || $parameter->isDefaultValueAvailable()) {
135:                 // !optional + defaultAvailable = func($a = null, $b) since 5.4.7
136:                 // optional + !defaultAvailable = i.e. Exception::__construct, mysqli::mysqli, ...
137:                 $res[$num] = $parameter->isDefaultValueAvailable() ? Reflection::getParameterDefaultValue($parameter) : null;
138:                 $optCount++;
139: 
140:             } else {
141:                 throw new ServiceCreationException("Parameter $$paramName in $methodName has no class type hint or default value, so its value must be specified.");
142:             }
143:         }
144: 
145:         // extra parameters
146:         while (array_key_exists(++$num, $arguments)) {
147:             $res[$num] = $arguments[$num];
148:             unset($arguments[$num]);
149:             $optCount = 0;
150:         }
151:         if ($arguments) {
152:             throw new ServiceCreationException("Unable to pass specified arguments to $methodName.");
153:         }
154: 
155:         return $optCount ? array_slice($res, 0, -$optCount) : $res;
156:     }
157: 
158: 
159:     /**
160:      * Removes ... and process constants recursively.
161:      * @return array
162:      */
163:     public static function filterArguments(array $args)
164:     {
165:         foreach ($args as $k => $v) {
166:             if ($v === '...') {
167:                 unset($args[$k]);
168:             } elseif (is_string($v) && preg_match('#^[\w\\\\]*::[A-Z][A-Z0-9_]*\z#', $v, $m)) {
169:                 $args[$k] = constant(ltrim($v, ':'));
170:             } elseif (is_array($v)) {
171:                 $args[$k] = self::filterArguments($v);
172:             } elseif ($v instanceof Statement) {
173:                 $tmp = self::filterArguments([$v->getEntity()]);
174:                 $args[$k] = new Statement($tmp[0], self::filterArguments($v->arguments));
175:             }
176:         }
177:         return $args;
178:     }
179: 
180: 
181:     /**
182:      * Replaces @extension with real extension name in service definition.
183:      * @param  mixed
184:      * @param  string
185:      * @return mixed
186:      */
187:     public static function prefixServiceName($config, $namespace)
188:     {
189:         if (is_string($config)) {
190:             if (strncmp($config, '@extension.', 10) === 0) {
191:                 $config = '@' . $namespace . '.' . substr($config, 11);
192:             }
193:         } elseif ($config instanceof Statement) {
194:             return new Statement(
195:                 self::prefixServiceName($config->getEntity(), $namespace),
196:                 self::prefixServiceName($config->arguments, $namespace)
197:             );
198:         } elseif (is_array($config)) {
199:             foreach ($config as &$val) {
200:                 $val = self::prefixServiceName($val, $namespace);
201:             }
202:         }
203:         return $config;
204:     }
205: 
206: 
207:     /**
208:      * Returns an annotation value.
209:      * @return string|null
210:      */
211:     public static function parseAnnotation(\Reflector $ref, $name)
212:     {
213:         if (!Reflection::areCommentsAvailable()) {
214:             throw new Nette\InvalidStateException('You have to enable phpDoc comments in opcode cache.');
215:         }
216:         $name = preg_quote($name, '#');
217:         if ($ref->getDocComment() && preg_match("#[\\s*]@$name(?:\\s++([^@]\\S*)?|$)#", trim($ref->getDocComment(), '/*'), $m)) {
218:             return isset($m[1]) ? $m[1] : '';
219:         }
220:     }
221: 
222: 
223:     /**
224:      * @return string|null
225:      */
226:     public static function getReturnType(\ReflectionFunctionAbstract $func)
227:     {
228:         if ($type = Reflection::getReturnType($func)) {
229:             return $type;
230:         } elseif ($type = preg_replace('#[|\s].*#', '', (string) self::parseAnnotation($func, 'return'))) {
231:             if ($type === 'object' || $type === 'mixed') {
232:                 return null;
233:             } elseif ($func instanceof \ReflectionMethod) {
234:                 return $type === 'static' || $type === '$this'
235:                     ? $func->getDeclaringClass()->getName()
236:                     : Reflection::expandClassName($type, $func->getDeclaringClass());
237:             } else {
238:                 return $type;
239:             }
240:         }
241:     }
242: 
243: 
244:     public static function normalizeClass($type)
245:     {
246:         return class_exists($type) || interface_exists($type)
247:             ? (new \ReflectionClass($type))->getName()
248:             : $type;
249:     }
250: }
251: 
Nette 2.4-20180703 API API documentation generated by ApiGen 2.8.0