1: <?php
2:
3: namespace Deimos\DI;
4:
5: abstract class DI
6: {
7:
8: 9: 10:
11: protected $storage = [];
12:
13: 14: 15:
16: protected $self;
17:
18: 19: 20: 21: 22:
23: public function __construct($init = true)
24: {
25: $this->self = $this;
26:
27: if ($init)
28: {
29: $this->configure();
30: }
31: }
32:
33: 34: 35: 36: 37: 38:
39: public function call($name, array $arguments = [])
40: {
41: $path = $this->path($name);
42: $row = $this->getFirst($path);
43: $last = array_pop($path);
44:
45: if (!empty($path))
46: {
47: $this->steps($row, $path);
48: }
49:
50: $isCallable = is_callable($row);
51:
52: if (!$isCallable && !$last)
53: {
54: return $row;
55: }
56:
57: return call_user_func_array(
58: $isCallable ? $row : [$row, $last],
59: (new Argument($this, $arguments))->get()
60: );
61: }
62:
63: 64: 65: 66:
67: protected function group($name, callable $callback)
68: {
69: list ($self, $this->self) = [$this->self, new Group()];
70: $self->storage[$name] = $this->self;
71: $callback();
72: $this->self = $self;
73: }
74:
75: 76: 77: 78:
79: protected function steps(&$row, array $keys)
80: {
81: foreach ($keys as $name)
82: {
83: $row = $row->{$name}();
84: }
85: }
86:
87: protected function build($name, callable $callback)
88: {
89: $this->value($name, $callback);
90: }
91:
92: protected function path($name)
93: {
94: return explode('.', $name);
95: }
96:
97: protected function getFirst(&$path)
98: {
99: $name = array_shift($path);
100: $object = $this->self->storage[$name];
101:
102: return $this->getInstance($object);
103: }
104:
105: public function get($name)
106: {
107: $path = $this->path($name);
108: $row = $this->getFirst($path);
109: $last = array_pop($path);
110:
111: if (!empty($path))
112: {
113: $this->steps($row, $path);
114: }
115:
116: if ($last && is_object($row))
117: {
118: if ($row instanceof self)
119: {
120: return $this->getInstance($row->self->storage[$last]);
121: }
122:
123: $row = $row->{$last}();
124: }
125:
126: return $this->getInstance($row);
127: }
128:
129: protected function getInstance($row)
130: {
131: if ($row instanceof Instance)
132: {
133: return $row->get();
134: }
135:
136: return $row;
137: }
138:
139: 140: 141: 142: 143: 144:
145: public function __call($name, array $arguments = [])
146: {
147: return $this->call($name, $arguments);
148: }
149:
150: 151: 152: 153: 154:
155: protected function value($name, $row, array $arguments = [])
156: {
157: $argument = new Argument($this, $arguments);
158: $arguments = $argument->get();
159: unset($argument);
160:
161: $this->self->storage[$name] =
162: is_callable($row) ?
163: call_user_func_array($row, $arguments) : $row;
164: }
165:
166: 167: 168: 169:
170: protected function callback($name, $callback)
171: {
172: $this->self->storage[$name] = $callback;
173: }
174:
175: protected function instance($name, $class, array $arguments = [])
176: {
177: $this->self->storage[$name] = new Instance(
178: $this,
179: $class,
180: new Argument($this, $arguments)
181: );
182: }
183:
184: 185: 186:
187: abstract protected function configure();
188:
189: }