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