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('Circular reference detected for variables: ' . implode(', ', array_keys($recursive)) . '.');
60:
61: } else {
62: $val = Nette\Utils\Arrays::get($params, explode('.', $part));
63: if ($recursive) {
64: $val = self::expand($val, $params, (is_array($recursive) ? $recursive : array()) + array($part => 1));
65: }
66: if (strlen($part) + 2 === strlen($var)) {
67: return $val;
68: }
69: if (!is_scalar($val)) {
70: throw new Nette\InvalidArgumentException("Unable to concatenate non-scalar parameter '$part' into '$var'.");
71: }
72: $res .= $val;
73: }
74: }
75: return $res;
76: }
77:
78:
79: 80: 81: 82: 83:
84: public static function autowireArguments(\ReflectionFunctionAbstract $method, array $arguments, $container)
85: {
86: $optCount = 0;
87: $num = -1;
88: $res = array();
89:
90: foreach ($method->getParameters() as $num => $parameter) {
91: if (array_key_exists($num, $arguments)) {
92: $res[$num] = $arguments[$num];
93: unset($arguments[$num]);
94: $optCount = 0;
95:
96: } elseif (array_key_exists($parameter->getName(), $arguments)) {
97: $res[$num] = $arguments[$parameter->getName()];
98: unset($arguments[$parameter->getName()]);
99: $optCount = 0;
100:
101: } elseif ($class = $parameter->getClassName()) {
102: $res[$num] = $container->getByType($class, FALSE);
103: if ($res[$num] === NULL) {
104: if ($parameter->allowsNull()) {
105: $optCount++;
106: } else {
107: 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.");
108: }
109: } else {
110: if ($container instanceof ContainerBuilder) {
111: $res[$num] = '@' . $res[$num];
112: }
113: $optCount = 0;
114: }
115:
116: } elseif ($parameter->isOptional()) {
117:
118: $res[$num] = $parameter->isDefaultValueAvailable() ? $parameter->getDefaultValue() : NULL;
119: $optCount++;
120:
121: } else {
122: throw new ServiceCreationException("Parameter $parameter has no type hint, so its value must be specified.");
123: }
124: }
125:
126:
127: while (array_key_exists(++$num, $arguments)) {
128: $res[$num] = $arguments[$num];
129: unset($arguments[$num]);
130: $optCount = 0;
131: }
132: if ($arguments) {
133: throw new ServiceCreationException("Unable to pass specified arguments to $method.");
134: }
135:
136: return $optCount ? array_slice($res, 0, -$optCount) : $res;
137: }
138:
139:
140: 141: 142: 143:
144: public static function getInjectProperties(Nette\Reflection\ClassType $class)
145: {
146: $res = array();
147: foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) {
148: $type = $property->getAnnotation('var');
149: if (!$property->getAnnotation('inject')) {
150: continue;
151:
152: } elseif (!$type) {
153: throw new Nette\InvalidStateException("Property $property has not @var annotation.");
154:
155: } elseif (!class_exists($type) && !interface_exists($type)) {
156: if ($type[0] !== '\\') {
157: $type = $property->getDeclaringClass()->getNamespaceName() . '\\' . $type;
158: }
159: if (!class_exists($type) && !interface_exists($type)) {
160: throw new Nette\InvalidStateException("Please use a fully qualified name of class/interface in @var annotation at $property property. Class '$type' cannot be found.");
161: }
162: }
163: $res[$property->getName()] = $type;
164: }
165: return $res;
166: }
167:
168:
169: }
170: