1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11:
12:
13:
14:
15: 16: 17: 18: 19: 20:
21: class DIContainerBuilder extends Object
22: {
23:
24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37:
38: public function addDefinitions(IDIContainer $container, array $definitions)
39: {
40: foreach ($definitions as $name => $definition) {
41: if (is_scalar($definition)) {
42: if (substr($definition, 0, 1) === '@') {
43: $definition = array('alias' => substr($definition, 1));
44: } else {
45: $definition = array('class' => $definition);
46: }
47: }
48:
49: $arguments = isset($definition['arguments']) ? $definition['arguments'] : array();
50: $expander = create_function('&$val', 'extract(NCFix::$vars['.NCFix::uses(array('container'=>$container)).'], EXTR_REFS);
51: if (substr($val, 0, 1) === \'@\') {
52: $val = $container->getService(substr($val, 1));
53: } elseif (is_string($val)) {
54: $val = Strings::expand($val, $container->params);
55: }
56: ');
57:
58: if (isset($definition['class']) || isset($definition['factory'])) {
59: if (isset($definition['class'])) {
60: $class = $definition['class'];
61: } else {
62: $class = NULL;
63: array_unshift($arguments, $definition['factory']);
64: }
65: $methods = isset($definition['methods']) ? $definition['methods'] : array();
66: $factory = create_function('$container', 'extract(NCFix::$vars['.NCFix::uses(array('class'=>$class,'arguments'=> $arguments,'methods'=> $methods,'expander'=> $expander)).'], EXTR_REFS);
67: array_walk_recursive($arguments, $expander);
68: if ($class) {
69: $class = Strings::expand($class, $container->params);
70: if ($arguments) {
71: $service = ClassReflection::from($class)->newInstanceArgs($arguments);
72: } else {
73: $service = new $class;
74: }
75: } else {
76: $factory = $arguments[0]; $arguments[0] = $container;
77: $service = call_user_func_array($factory, $arguments);
78: }
79:
80: array_walk_recursive($methods, $expander);
81: foreach ($methods as $method) {
82: call_user_func_array(array($service, $method[0]), isset($method[1]) ? $method[1] : array());
83: }
84:
85: return $service;
86: ');
87:
88: } elseif (isset($definition['alias'])) {
89: $factory = create_function('$container', 'extract(NCFix::$vars['.NCFix::uses(array('definition'=>$definition)).'], EXTR_REFS);
90: return $container->getService($definition[\'alias\']);
91: ');
92: } else {
93: throw new InvalidStateException("The definition of service '$name' is missing factory method.");
94: }
95:
96: if (isset($definition['tags'])) {
97: $tags = (array) $definition['tags'];
98: array_walk_recursive($tags, $expander);
99: } else {
100: $tags = NULL;
101: }
102: $container->addService($name, $factory, $tags);
103: }
104: }
105:
106:
107:
108: public function generateCode(array $definitions)
109: {
110: $code = '';
111: foreach ($definitions as $name => $definition) {
112: $name = $this->varExport($name);
113: if (is_scalar($definition)) {
114: if (substr($definition, 0, 1) === '@') {
115: $definition = array('alias' => substr($definition, 1));
116: } else {
117: $factory = $this->varExport($definition);
118: $code .= "\$container->addService($name, $factory);\n\n";
119: continue;
120: }
121: }
122:
123: if (isset($definition['class']) || isset($definition['factory'])) {
124: $arguments = $this->argsExport(isset($definition['arguments']) ? $definition['arguments'] : array());
125: $factory = "function(\$container) {\n\t";
126: $factory .= isset($definition['class'])
127: ? '$class = ' . $this->argsExport(array($definition['class'])) . '; $service = new $class(' . $arguments . ");\n"
128: : "\$service = call_user_func(\n\t\t" . $this->argsExport(array($definition['factory']))
129: . ",\n\t\t\$container" . ($arguments ? ",\n\t\t$arguments" : '') . "\n\t);\n";
130:
131: if (isset($definition['methods'])) {
132: foreach ($definition['methods'] as $method) {
133: $args = isset($method[1]) ? $this->argsExport($method[1]) : '';
134: $factory .= "\t\$service->$method[0]($args);\n";
135: }
136: }
137: $factory .= "\treturn \$service;\n}";
138:
139: } elseif (isset($definition['alias'])) {
140: $factory = $this->varExport($definition['alias']);
141: $factory = "function(\$container) {\n\treturn \$container->getService($factory);\n}";
142: } else {
143: throw new InvalidStateException("The definition of service '$name' is missing factory method.");
144: }
145:
146: $tags = isset($definition['tags']) ? $this->argsExport(array($definition['tags'])) : 'NULL';
147: $code .= "\$container->addService($name, $factory, $tags);\n\n";
148: }
149: return $code;
150: }
151:
152:
153:
154: private function argsExport($args)
155: {
156: $args = implode(', ', array_map(array($this, 'varExport'), $args));
157: $args = preg_replace("#(?<!\\\)'@(\w+)'#", '\$container->getService(\'$1\')', $args);
158: $args = preg_replace("#(?<!\\\)'%([\w-]+)%'#", '\$container->params[\'$1\']', $args);
159: $args = preg_replace("#(?<!\\\)'(?:[^'\\\]|\\\.)*%(?:[^'\\\]|\\\.)*'#", 'Strings::expand($0, \$container->params)', $args);
160: return $args;
161: }
162:
163:
164:
165: private function varExport($arg)
166: {
167: return preg_replace('#\n *#', ' ', var_export($arg, TRUE));
168: }
169:
170: }
171: