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