1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11:
12:
13:
14:
15: 16: 17: 18: 19:
20: class Context extends FreezableObject implements IContext
21: {
22:
23: private $registry = array();
24:
25:
26: private $factories = array();
27:
28:
29:
30: 31: 32: 33: 34: 35: 36: 37: 38:
39: public function addService($name, $service, $singleton = TRUE, array $options = NULL)
40: {
41: $this->updating();
42: if (!is_string($name) || $name === '') {
43: throw new InvalidArgumentException("Service name must be a non-empty string, " . gettype($name) . " given.");
44: }
45:
46: $lower = strtolower($name);
47: if (isset($this->registry[$lower])) { 48: throw new AmbiguousServiceException("Service named '$name' has already been registered.");
49: }
50:
51: if ($service instanceof self) {
52: $this->registry[$lower] = & $service->registry[$lower];
53: $this->factories[$lower] = & $service->factories[$lower];
54:
55: } elseif (is_object($service) && !($service instanceof Closure || $service instanceof Callback)) {
56: if (!$singleton || $options) {
57: throw new InvalidArgumentException("Service named '$name' is an instantiated object and must therefore be singleton without options.");
58: }
59: $this->registry[$lower] = $service;
60:
61: } else {
62: if (!$service) {
63: throw new InvalidArgumentException("Service named '$name' is empty.");
64: }
65: $this->factories[$lower] = array($service, $singleton, $options);
66: $this->registry[$lower] = & $this->factories[$lower][3]; 67: }
68: return $this;
69: }
70:
71:
72:
73: 74: 75: 76:
77: public function removeService($name)
78: {
79: $this->updating();
80: if (!is_string($name) || $name === '') {
81: throw new InvalidArgumentException("Service name must be a non-empty string, " . gettype($name) . " given.");
82: }
83:
84: $lower = strtolower($name);
85: unset($this->registry[$lower], $this->factories[$lower]);
86: }
87:
88:
89:
90: 91: 92: 93: 94: 95:
96: public function getService($name, array $options = NULL)
97: {
98: if (!is_string($name) || $name === '') {
99: throw new InvalidArgumentException("Service name must be a non-empty string, " . gettype($name) . " given.");
100: }
101:
102: $lower = strtolower($name);
103:
104: if (isset($this->registry[$lower])) { 105: if ($options) {
106: throw new InvalidArgumentException("Service named '$name' is singleton and therefore can not have options.");
107: }
108: return $this->registry[$lower];
109:
110: } elseif (isset($this->factories[$lower])) {
111: list($factory, $singleton, $defOptions) = $this->factories[$lower];
112:
113: if ($singleton && $options) {
114: throw new InvalidArgumentException("Service named '$name' is singleton and therefore can not have options.");
115:
116: } elseif ($defOptions) {
117: $options = $options ? $options + $defOptions : $defOptions;
118: }
119:
120: if (is_string($factory) && strpos($factory, ':') === FALSE) { 121: if ($a = strrpos($factory, '\\')) $factory = substr($factory, $a + 1); 122: if (!class_exists($factory)) {
123: throw new AmbiguousServiceException("Cannot instantiate service '$name', class '$factory' not found.");
124: }
125: $service = new $factory;
126: if ($options) {
127: if (method_exists($service, 'setOptions')) {
128: $service->setOptions($options); 129: } else {
130: throw new InvalidStateException("Unable to set options, method $factory::setOptions() is missing.");
131: }
132: }
133:
134: } else { 135: $factory = callback($factory);
136: if (!$factory->isCallable()) {
137: throw new InvalidStateException("Cannot instantiate service '$name', handler '$factory' is not callable.");
138: }
139: $service = $factory->invoke($options);
140: if (!is_object($service)) {
141: throw new AmbiguousServiceException("Cannot instantiate service '$name', value returned by '$factory' is not object.");
142: }
143: }
144:
145: if ($singleton) {
146: $this->registry[$lower] = $service;
147: unset($this->factories[$lower]);
148: }
149: return $service;
150:
151: } else {
152: throw new InvalidStateException("Service '$name' not found.");
153: }
154: }
155:
156:
157:
158: 159: 160: 161: 162: 163:
164: public function hasService($name, $created = FALSE)
165: {
166: if (!is_string($name) || $name === '') {
167: throw new InvalidArgumentException("Service name must be a non-empty string, " . gettype($name) . " given.");
168: }
169:
170: $lower = strtolower($name);
171: return isset($this->registry[$lower]) || (!$created && isset($this->factories[$lower]));
172: }
173:
174: }
175: