Packages

  • Nette
    • Application
      • Diagnostics
      • Responses
      • Routers
      • UI
    • Caching
      • Storages
    • ComponentModel
    • Config
      • Adapters
      • Extensions
    • Database
      • Diagnostics
      • Drivers
      • Reflection
      • Table
    • DI
      • Diagnostics
    • Diagnostics
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Latte
      • Macros
    • Loaders
    • Localization
    • Mail
    • Reflection
    • Security
      • Diagnostics
    • Templating
    • Utils
      • PhpGenerator
  • NetteModule
  • None
  • PHP

Classes

  • AppForm
  • Control
  • Multiplier
  • Presenter
  • PresenterComponent

Interfaces

  • IRenderable
  • ISignalReceiver
  • IStatePersistent

Exceptions

  • BadSignalException
  • InvalidLinkException
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (http://nette.org)
  5:  *
  6:  * Copyright (c) 2004 David Grudl (http://davidgrudl.com)
  7:  *
  8:  * For the full copyright and license information, please view
  9:  * the file license.txt that was distributed with this source code.
 10:  * @package Nette\Application\UI
 11:  */
 12: 
 13: 
 14: 
 15: /**
 16:  * PresenterComponent is the base class for all Presenter components.
 17:  *
 18:  * Components are persistent objects located on a presenter. They have ability to own
 19:  * other child components, and interact with user. Components have properties
 20:  * for storing their status, and responds to user command.
 21:  *
 22:  * @author     David Grudl
 23:  *
 24:  * @property-read Presenter $presenter
 25:  * @property-read string $uniqueId
 26:  * @package Nette\Application\UI
 27:  */
 28: abstract class PresenterComponent extends ComponentContainer implements ISignalReceiver, IStatePersistent, ArrayAccess
 29: {
 30:     /** @var array */
 31:     protected $params = array();
 32: 
 33: 
 34: 
 35:     /**
 36:      */
 37:     public function __construct(IComponentContainer $parent = NULL, $name = NULL)
 38:     {
 39:         $this->monitor('Presenter');
 40:         parent::__construct($parent, $name);
 41:     }
 42: 
 43: 
 44: 
 45:     /**
 46:      * Returns the presenter where this component belongs to.
 47:      * @param  bool   throw exception if presenter doesn't exist?
 48:      * @return Presenter|NULL
 49:      */
 50:     public function getPresenter($need = TRUE)
 51:     {
 52:         return $this->lookup('Presenter', $need);
 53:     }
 54: 
 55: 
 56: 
 57:     /**
 58:      * Returns a fully-qualified name that uniquely identifies the component
 59:      * within the presenter hierarchy.
 60:      * @return string
 61:      */
 62:     public function getUniqueId()
 63:     {
 64:         return $this->lookupPath('Presenter', TRUE);
 65:     }
 66: 
 67: 
 68: 
 69:     /**
 70:      * This method will be called when the component (or component's parent)
 71:      * becomes attached to a monitored object. Do not call this method yourself.
 72:      * @param  IComponent
 73:      * @return void
 74:      */
 75:     protected function attached($presenter)
 76:     {
 77:         if ($presenter instanceof Presenter) {
 78:             $this->loadState($presenter->popGlobalParameters($this->getUniqueId()));
 79:         }
 80:     }
 81: 
 82: 
 83: 
 84:     /**
 85:      * Calls public method if exists.
 86:      * @param  string
 87:      * @param  array
 88:      * @return bool  does method exist?
 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:      * Checks for requirements such as authorization.
108:      * @return void
109:      */
110:     public function checkRequirements($element)
111:     {
112:     }
113: 
114: 
115: 
116:     /**
117:      * Access to reflection.
118:      * @return PresenterComponentReflection
119:      */
120:     public function getReflection()
121:     {
122:         return new PresenterComponentReflection($this);
123:     }
124: 
125: 
126: 
127:     /********************* interface IStatePersistent ****************d*g**/
128: 
129: 
130: 
131:     /**
132:      * Loads state informations.
133:      * @param  array
134:      * @return void
135:      */
136:     public function loadState(array $params)
137:     {
138:         foreach ($this->getReflection()->getPersistentParams() as $nm => $meta) {
139:             if (isset($params[$nm])) { // ignore NULL values
140:                 if (isset($meta['def'])) {
141:                     if (is_array($params[$nm]) && !is_array($meta['def'])) {
142:                         $params[$nm] = $meta['def']; // prevents array to scalar conversion
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:      * Saves state informations for next request.
159:      * @param  array
160:      * @param  PresenterComponentReflection (internal, used by Presenter)
161:      * @return void
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]; // injected value
170: 
171:             } elseif (array_key_exists($nm, $params)) { // $params[$nm] === NULL
172:                 continue; // means skip
173: 
174:             } elseif (!isset($meta['since']) || $this instanceof $meta['since']) {
175:                 $val = $this->$nm; // object property value
176: 
177:             } else {
178:                 continue; // ignored parameter
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:      * Returns component param.
205:      * If no key is passed, returns the entire array.
206:      * @param  string key
207:      * @param  mixed  default value
208:      * @return mixed
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:      * Returns a fully-qualified name that uniquely identifies the parameter.
227:      * @param  string
228:      * @return string
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:     /** @deprecated */
239:     function getParam($name = NULL, $default = NULL)
240:     {
241:         //trigger_error(__METHOD__ . '() is deprecated; use getParameter() instead.', E_USER_WARNING);
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:     /** @deprecated */
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:      * Returns array of classes persistent parameters. They have public visibility and are non-static.
264:      * This default implementation detects persistent parameters by annotation @persistent.
265:      * @return array
266:      */
267:     public static function getPersistentParams()
268:     {
269:         $arg = func_get_arg(0);
270:         $rc = new ClassReflection($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:     /********************* interface ISignalReceiver ****************d*g**/
283: 
284: 
285: 
286:     /**
287:      * Calls signal handler method.
288:      * @param  string
289:      * @return void
290:      * @throws BadSignalException if there is not handler method
291:      */
292:     public function signalReceived($signal)
293:     {
294:         if (!$this->tryCall($this->formatSignalMethod($signal), $this->params)) {
295:             $class = get_class($this);
296:             throw new BadSignalException("There is no handler for signal '$signal' in class $class.");
297:         }
298:     }
299: 
300: 
301: 
302:     /**
303:      * Formats signal handler method name -> case sensitivity doesn't matter.
304:      * @param  string
305:      * @return string
306:      */
307:     public function formatSignalMethod($signal)
308:     {
309:         return $signal == NULL ? NULL : 'handle' . $signal; // intentionally ==
310:     }
311: 
312: 
313: 
314:     /********************* navigation ****************d*g**/
315: 
316: 
317: 
318:     /**
319:      * Generates URL to presenter, action or signal.
320:      * @param  string   destination in format "[[module:]presenter:]action" or "signal!" or "this"
321:      * @param  array|mixed
322:      * @return string
323:      * @throws InvalidLinkException
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 (InvalidLinkException $e) {
336:             return $this->getPresenter()->handleInvalidLink($e);
337:         }
338:     }
339: 
340: 
341: 
342:     /**
343:      * Returns destination as Link object.
344:      * @param  string   destination in format "[[module:]presenter:]view" or "signal!"
345:      * @param  array|mixed
346:      * @return Link
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 Link($this, $destination, $args);
356:     }
357: 
358: 
359: 
360:     /**
361:      * Determines whether it links to the current page.
362:      * @param  string   destination in format "[[module:]presenter:]action" or "signal!" or "this"
363:      * @param  array|mixed
364:      * @return bool
365:      * @throws InvalidLinkException
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:      * Redirect to another presenter, action or signal.
383:      * @param  int      [optional] HTTP error code
384:      * @param  string   destination in format "[[module:]presenter:]view" or "signal!"
385:      * @param  array|mixed
386:      * @return void
387:      * @throws AbortException
388:      */
389:     public function redirect($code, $destination = NULL, $args = array())
390:     {
391:         if (!is_numeric($code)) { // first parameter is optional
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:     /********************* interface ArrayAccess ****************d*g**/
411: 
412: 
413: 
414:     /**
415:      * Adds the component to the container.
416:      * @param  string  component name
417:      * @param  IComponent
418:      * @return void
419:      */
420:     final public function offsetSet($name, $component)
421:     {
422:         $this->addComponent($component, $name);
423:     }
424: 
425: 
426: 
427:     /**
428:      * Returns component specified by name. Throws exception if component doesn't exist.
429:      * @param  string  component name
430:      * @return IComponent
431:      * @throws InvalidArgumentException
432:      */
433:     final public function offsetGet($name)
434:     {
435:         return $this->getComponent($name, TRUE);
436:     }
437: 
438: 
439: 
440:     /**
441:      * Does component specified by name exists?
442:      * @param  string  component name
443:      * @return bool
444:      */
445:     final public function offsetExists($name)
446:     {
447:         return $this->getComponent($name, FALSE) !== NULL;
448:     }
449: 
450: 
451: 
452:     /**
453:      * Removes component from the container.
454:      * @param  string  component name
455:      * @return void
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: 
Nette Framework 2.0.1 (for PHP 5.2, un-prefixed) API API documentation generated by ApiGen 2.7.0