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