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:
230: final public function getParameterId($name)
231: {
232: $uid = $this->getUniqueId();
233: return $uid === '' ? $name : $uid . self::NAME_SEPARATOR . $name;
234: }
235:
236:
237:
238:
239: function getParam($name = NULL, $default = NULL)
240: {
241:
242: if (func_num_args() === 0) {
243: return $this->params;
244: } elseif (isset($this->params[$name])) {
245: return $this->params[$name];
246: } else {
247: return $default;
248: }
249: }
250:
251:
252:
253:
254: function getParamId($name)
255: {
256: trigger_error(__METHOD__ . '() is deprecated; use getParameterId() instead.', E_USER_WARNING);
257: return $this->getParameterId($name);
258: }
259:
260:
261:
262: 263: 264: 265: 266:
267: public static function getPersistentParams()
268: {
269: $arg = func_get_arg(0);
270: $rc = new NClassReflection($arg);
271: $params = array();
272: foreach ($rc->getProperties(ReflectionProperty::IS_PUBLIC) as $rp) {
273: if (!$rp->isStatic() && $rp->hasAnnotation('persistent')) {
274: $params[] = $rp->getName();
275: }
276: }
277: return $params;
278: }
279:
280:
281:
282:
283:
284:
285:
286: 287: 288: 289: 290: 291:
292: public function signalReceived($signal)
293: {
294: if (!$this->tryCall($this->formatSignalMethod($signal), $this->params)) {
295: $class = get_class($this);
296: throw new NBadSignalException("There is no handler for signal '$signal' in class $class.");
297: }
298: }
299:
300:
301:
302: 303: 304: 305: 306:
307: public function formatSignalMethod($signal)
308: {
309: return $signal == NULL ? NULL : 'handle' . $signal;
310: }
311:
312:
313:
314:
315:
316:
317:
318: 319: 320: 321: 322: 323: 324:
325: public function link($destination, $args = array())
326: {
327: if (!is_array($args)) {
328: $args = func_get_args();
329: array_shift($args);
330: }
331:
332: try {
333: return $this->getPresenter()->createRequest($this, $destination, $args, 'link');
334:
335: } catch (NInvalidLinkException $e) {
336: return $this->getPresenter()->handleInvalidLink($e);
337: }
338: }
339:
340:
341:
342: 343: 344: 345: 346: 347:
348: public function lazyLink($destination, $args = array())
349: {
350: if (!is_array($args)) {
351: $args = func_get_args();
352: array_shift($args);
353: }
354:
355: return new NLink($this, $destination, $args);
356: }
357:
358:
359:
360: 361: 362: 363: 364: 365: 366:
367: public function isLinkCurrent($destination = NULL, $args = array())
368: {
369: if ($destination !== NULL) {
370: if (!is_array($args)) {
371: $args = func_get_args();
372: array_shift($args);
373: }
374: $this->link($destination, $args);
375: }
376: return $this->getPresenter()->getLastCreatedRequestFlag('current');
377: }
378:
379:
380:
381: 382: 383: 384: 385: 386: 387: 388:
389: public function redirect($code, $destination = NULL, $args = array())
390: {
391: if (!is_numeric($code)) {
392: $args = $destination;
393: $destination = $code;
394: $code = NULL;
395: }
396:
397: if (!is_array($args)) {
398: $args = func_get_args();
399: if (is_numeric(array_shift($args))) {
400: array_shift($args);
401: }
402: }
403:
404: $presenter = $this->getPresenter();
405: $presenter->redirectUrl($presenter->createRequest($this, $destination, $args, 'redirect'), $code);
406: }
407:
408:
409:
410:
411:
412:
413:
414: 415: 416: 417: 418: 419:
420: final public function offsetSet($name, $component)
421: {
422: $this->addComponent($component, $name);
423: }
424:
425:
426:
427: 428: 429: 430: 431: 432:
433: final public function offsetGet($name)
434: {
435: return $this->getComponent($name, TRUE);
436: }
437:
438:
439:
440: 441: 442: 443: 444:
445: final public function offsetExists($name)
446: {
447: return $this->getComponent($name, FALSE) !== NULL;
448: }
449:
450:
451:
452: 453: 454: 455: 456:
457: final public function offsetUnset($name)
458: {
459: $component = $this->getComponent($name, FALSE);
460: if ($component !== NULL) {
461: $this->removeComponent($component);
462: }
463: }
464:
465: }
466: