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