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