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:
232: final public function getParameterId($name)
233: {
234: $uid = $this->getUniqueId();
235: return $uid === '' ? $name : $uid . self::NAME_SEPARATOR . $name;
236: }
237:
238:
239:
240:
241: function getParam($name = NULL, $default = NULL)
242: {
243:
244: if (func_num_args() === 0) {
245: return $this->params;
246: } elseif (isset($this->params[$name])) {
247: return $this->params[$name];
248: } else {
249: return $default;
250: }
251: }
252:
253:
254:
255:
256: function getParamId($name)
257: {
258: trigger_error(__METHOD__ . '() is deprecated; use getParameterId() instead.', E_USER_WARNING);
259: return $this->getParameterId($name);
260: }
261:
262:
263:
264: 265: 266: 267: 268:
269: public static function getPersistentParams()
270: {
271: $rc = new Nette\Reflection\ClassType(get_called_class());
272: $params = array();
273: foreach ($rc->getProperties(\ReflectionProperty::IS_PUBLIC) as $rp) {
274: if (!$rp->isStatic() && $rp->hasAnnotation('persistent')) {
275: $params[] = $rp->getName();
276: }
277: }
278: return $params;
279: }
280:
281:
282:
283:
284:
285:
286:
287: 288: 289: 290: 291: 292:
293: public function signalReceived($signal)
294: {
295: if (!$this->tryCall($this->formatSignalMethod($signal), $this->params)) {
296: $class = get_class($this);
297: throw new BadSignalException("There is no handler for signal '$signal' in class $class.");
298: }
299: }
300:
301:
302:
303: 304: 305: 306: 307:
308: public function formatSignalMethod($signal)
309: {
310: return $signal == NULL ? NULL : 'handle' . $signal;
311: }
312:
313:
314:
315:
316:
317:
318:
319: 320: 321: 322: 323: 324: 325:
326: public function link($destination, $args = array())
327: {
328: if (!is_array($args)) {
329: $args = func_get_args();
330: array_shift($args);
331: }
332:
333: try {
334: return $this->getPresenter()->createRequest($this, $destination, $args, 'link');
335:
336: } catch (InvalidLinkException $e) {
337: return $this->getPresenter()->handleInvalidLink($e);
338: }
339: }
340:
341:
342:
343: 344: 345: 346: 347: 348:
349: public function lazyLink($destination, $args = array())
350: {
351: if (!is_array($args)) {
352: $args = func_get_args();
353: array_shift($args);
354: }
355:
356: return new Link($this, $destination, $args);
357: }
358:
359:
360:
361: 362: 363: 364: 365: 366: 367:
368: public function isLinkCurrent($destination = NULL, $args = array())
369: {
370: if ($destination !== NULL) {
371: if (!is_array($args)) {
372: $args = func_get_args();
373: array_shift($args);
374: }
375: $this->link($destination, $args);
376: }
377: return $this->getPresenter()->getLastCreatedRequestFlag('current');
378: }
379:
380:
381:
382: 383: 384: 385: 386: 387: 388: 389:
390: public function redirect($code, $destination = NULL, $args = array())
391: {
392: if (!is_numeric($code)) {
393: $args = $destination;
394: $destination = $code;
395: $code = NULL;
396: }
397:
398: if (!is_array($args)) {
399: $args = func_get_args();
400: if (is_numeric(array_shift($args))) {
401: array_shift($args);
402: }
403: }
404:
405: $presenter = $this->getPresenter();
406: $presenter->redirectUrl($presenter->createRequest($this, $destination, $args, 'redirect'), $code);
407: }
408:
409:
410:
411:
412:
413:
414:
415: 416: 417: 418: 419: 420:
421: final public function offsetSet($name, $component)
422: {
423: $this->addComponent($component, $name);
424: }
425:
426:
427:
428: 429: 430: 431: 432: 433:
434: final public function offsetGet($name)
435: {
436: return $this->getComponent($name, TRUE);
437: }
438:
439:
440:
441: 442: 443: 444: 445:
446: final public function offsetExists($name)
447: {
448: return $this->getComponent($name, FALSE) !== NULL;
449: }
450:
451:
452:
453: 454: 455: 456: 457:
458: final public function offsetUnset($name)
459: {
460: $component = $this->getComponent($name, FALSE);
461: if ($component !== NULL) {
462: $this->removeComponent($component);
463: }
464: }
465:
466: }
467: