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