1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette\DI;
9:
10: use Nette;
11:
12:
13: 14: 15: 16: 17:
18: class Helpers
19: {
20:
21: 22: 23: 24: 25: 26: 27: 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: 85: 86: 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()) {
106: $res[$num] = $container->getByType($class, FALSE);
107: if ($res[$num] === NULL) {
108: if ($parameter->allowsNull()) {
109: $optCount++;
110: } else {
111: throw new ServiceCreationException("No service of type {$class} found. Make sure the type hint in $method is written correctly and service of this type is registered.");
112: }
113: } else {
114: if ($container instanceof ContainerBuilder) {
115: $res[$num] = '@' . $res[$num];
116: }
117: $optCount = 0;
118: }
119:
120: } elseif ($parameter->isOptional()) {
121:
122: $res[$num] = $parameter->isDefaultValueAvailable() ? $parameter->getDefaultValue() : NULL;
123: $optCount++;
124:
125: } else {
126: throw new ServiceCreationException("Parameter $parameter has no type hint, so its value must be specified.");
127: }
128: }
129:
130:
131: while (array_key_exists(++$num, $arguments)) {
132: $res[$num] = $arguments[$num];
133: unset($arguments[$num]);
134: $optCount = 0;
135: }
136: if ($arguments) {
137: throw new ServiceCreationException("Unable to pass specified arguments to $method.");
138: }
139:
140: return $optCount ? array_slice($res, 0, -$optCount) : $res;
141: }
142:
143:
144: 145: 146: 147:
148: public static function getInjectProperties(Nette\Reflection\ClassType $class)
149: {
150: $res = array();
151: foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) {
152: $type = $property->getAnnotation('var');
153: if (!$property->getAnnotation('inject')) {
154: continue;
155:
156: } elseif (!$type) {
157: throw new Nette\InvalidStateException("Property $property has not @var annotation.");
158: }
159:
160: $type = Nette\Reflection\AnnotationsParser::expandClassName($type, $property->getDeclaringClass());
161: if (!class_exists($type) && !interface_exists($type)) {
162: throw new Nette\InvalidStateException("Class or interface '$type' used in @var annotation at $property not found.");
163: }
164: $res[$property->getName()] = $type;
165: }
166: return $res;
167: }
168:
169:
170: }
171: