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