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