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