1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11:
12:
13:
14:
15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27:
28: abstract class PresenterComponent extends ComponentContainer implements ISignalReceiver, IStatePersistent, ArrayAccess
29: {
30:
31: protected $params = array();
32:
33:
34: 35: 36: 37: 38:
39: public function getPresenter($need = TRUE)
40: {
41: return $this->lookup('Presenter', $need);
42: }
43:
44:
45: 46: 47: 48: 49:
50: public function getUniqueId()
51: {
52: return $this->lookupPath('Presenter', TRUE);
53: }
54:
55:
56: 57: 58: 59: 60: 61:
62: protected function attached($presenter)
63: {
64: if ($presenter instanceof Presenter) {
65: $this->loadState($presenter->popGlobalParameters($this->getUniqueId()));
66: }
67: }
68:
69:
70: 71: 72:
73: protected function validateParent(IComponentContainer $parent)
74: {
75: parent::validateParent($parent);
76: $this->monitor('Presenter');
77: }
78:
79:
80: 81: 82: 83: 84: 85:
86: protected function tryCall($method, array $params)
87: {
88: $rc = $this->getReflection();
89: if ($rc->hasMethod($method)) {
90: $rm = $rc->getMethod($method);
91: if ($rm->isPublic() && !$rm->isAbstract() && !$rm->isStatic()) {
92: $this->checkRequirements($rm);
93: $rm->invokeArgs($this, $rc->combineArgs($rm, $params));
94: return TRUE;
95: }
96: }
97: return FALSE;
98: }
99:
100:
101: 102: 103: 104:
105: public function checkRequirements($element)
106: {
107: }
108:
109:
110: 111: 112: 113:
114: public function getReflection()
115: {
116: return new PresenterComponentReflection($this);
117: }
118:
119:
120:
121:
122:
123: 124: 125: 126: 127:
128: public function loadState(array $params)
129: {
130: $reflection = $this->getReflection();
131: foreach ($reflection->getPersistentParams() as $name => $meta) {
132: if (isset($params[$name])) {
133: $type = gettype($meta['def'] === NULL ? $params[$name] : $meta['def']);
134: if (!$reflection->convertType($params[$name], $type)) {
135: throw new BadRequestException("Invalid value for persistent parameter '$name' in '{$this->getName()}', expected " . ($type === 'NULL' ? 'scalar' : $type) . ".");
136: }
137: $this->$name = & $params[$name];
138: } else {
139: $params[$name] = & $this->$name;
140: }
141: }
142: $this->params = $params;
143: }
144:
145:
146: 147: 148: 149: 150: 151:
152: public function saveState(array & $params, $reflection = NULL)
153: {
154: $reflection = $reflection === NULL ? $this->getReflection() : $reflection;
155: foreach ($reflection->getPersistentParams() as $name => $meta) {
156:
157: if (isset($params[$name])) {
158:
159:
160: } elseif (array_key_exists($name, $params)) {
161: continue;
162:
163: } elseif (!isset($meta['since']) || $this instanceof $meta['since']) {
164: $params[$name] = $this->$name;
165:
166: } else {
167: continue;
168: }
169:
170: $type = gettype($meta['def'] === NULL ? $params[$name] : $meta['def']);
171: if (!PresenterComponentReflection::convertType($params[$name], $type)) {
172: throw new InvalidLinkException("Invalid value for persistent parameter '$name' in '{$this->getName()}', expected " . ($type === 'NULL' ? 'scalar' : $type) . ".");
173: }
174:
175: if ($params[$name] === $meta['def'] || ($meta['def'] === NULL && is_scalar($params[$name]) && (string) $params[$name] === '')) {
176: $params[$name] = NULL;
177: }
178: }
179: }
180:
181:
182: 183: 184: 185: 186: 187: 188:
189: final public function getParameter($name = NULL, $default = NULL)
190: {
191: if (func_num_args() === 0) {
192: return $this->params;
193:
194: } elseif (isset($this->params[$name])) {
195: return $this->params[$name];
196:
197: } else {
198: return $default;
199: }
200: }
201:
202:
203: 204: 205: 206: 207:
208: final public function getParameterId($name)
209: {
210: $uid = $this->getUniqueId();
211: return $uid === '' ? $name : $uid . self::NAME_SEPARATOR . $name;
212: }
213:
214:
215:
216: function getParam($name = NULL, $default = NULL)
217: {
218:
219: return func_num_args() ? $this->getParameter($name, $default) : $this->getParameter();
220: }
221:
222:
223:
224: function getParamId($name)
225: {
226: trigger_error(__METHOD__ . '() is deprecated; use getParameterId() instead.', E_USER_WARNING);
227: return $this->getParameterId($name);
228: }
229:
230:
231: 232: 233: 234: 235:
236: public static function getPersistentParams()
237: {
238: $rc = new ClassReflection(func_get_arg(0));
239: $params = array();
240: foreach ($rc->getProperties(ReflectionProperty::IS_PUBLIC) as $rp) {
241: if (!$rp->isStatic() && $rp->hasAnnotation('persistent')) {
242: $params[] = $rp->getName();
243: }
244: }
245: return $params;
246: }
247:
248:
249:
250:
251:
252: 253: 254: 255: 256: 257:
258: public function signalReceived($signal)
259: {
260: if (!$this->tryCall($this->formatSignalMethod($signal), $this->params)) {
261: $class = get_class($this);
262: throw new BadSignalException("There is no handler for signal '$signal' in class $class.");
263: }
264: }
265:
266:
267: 268: 269: 270: 271:
272: public function formatSignalMethod($signal)
273: {
274: return $signal == NULL ? NULL : 'handle' . $signal;
275: }
276:
277:
278:
279:
280:
281: 282: 283: 284: 285: 286: 287:
288: public function link($destination, $args = array())
289: {
290: try {
291: $_args=func_get_args(); return $this->getPresenter()->createRequest($this, $destination, is_array($args) ? $args : array_slice($_args, 1), 'link');
292:
293: } catch (InvalidLinkException $e) {
294: return $this->getPresenter()->handleInvalidLink($e);
295: }
296: }
297:
298:
299: 300: 301: 302: 303: 304:
305: public function lazyLink($destination, $args = array())
306: {
307: $_args=func_get_args(); return new Link($this, $destination, is_array($args) ? $args : array_slice($_args, 1));
308: }
309:
310:
311: 312: 313: 314: 315: 316: 317:
318: public function isLinkCurrent($destination = NULL, $args = array())
319: {
320: if ($destination !== NULL) {
321: $_args=func_get_args(); $this->getPresenter()->createRequest($this, $destination, is_array($args) ? $args : array_slice($_args, 1), 'test');
322: }
323: return $this->getPresenter()->getLastCreatedRequestFlag('current');
324: }
325:
326:
327: 328: 329: 330: 331: 332: 333: 334:
335: public function redirect($code, $destination = NULL, $args = array())
336: {
337: if (!is_numeric($code)) {
338: $args = $destination;
339: $destination = $code;
340: $code = NULL;
341: }
342:
343: if (!is_array($args)) {
344: $args = array_slice(func_get_args(), is_numeric($code) ? 2 : 1);
345: }
346:
347: $presenter = $this->getPresenter();
348: $presenter->redirectUrl($presenter->createRequest($this, $destination, $args, 'redirect'), $code);
349: }
350:
351:
352:
353:
354:
355: 356: 357: 358: 359: 360:
361: final public function offsetSet($name, $component)
362: {
363: $this->addComponent($component, $name);
364: }
365:
366:
367: 368: 369: 370: 371: 372:
373: final public function offsetGet($name)
374: {
375: return $this->getComponent($name, TRUE);
376: }
377:
378:
379: 380: 381: 382: 383:
384: final public function offsetExists($name)
385: {
386: return $this->getComponent($name, FALSE) !== NULL;
387: }
388:
389:
390: 391: 392: 393: 394:
395: final public function offsetUnset($name)
396: {
397: $component = $this->getComponent($name, FALSE);
398: if ($component !== NULL) {
399: $this->removeComponent($component);
400: }
401: }
402:
403: }
404: