Namespaces

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

Classes

  • Control
  • Form
  • Presenter
  • PresenterComponent

Interfaces

  • IPartiallyRenderable
  • IRenderable
  • ISignalReceiver
  • IStatePersistent

Exceptions

  • BadSignalException
  • InvalidLinkException
  • Overview
  • Namespace
  • Class
  • Tree
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (http://nette.org)
  5:  *
  6:  * Copyright (c) 2004, 2011 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:  */
 11: 
 12: namespace Nette\Application\UI;
 13: 
 14: use Nette;
 15: 
 16: 
 17: 
 18: /**
 19:  * PresenterComponent is the base class for all Presenter components.
 20:  *
 21:  * Components are persistent objects located on a presenter. They have ability to own
 22:  * other child components, and interact with user. Components have properties
 23:  * for storing their status, and responds to user command.
 24:  *
 25:  * @author     David Grudl
 26:  *
 27:  * @property-read Presenter $presenter
 28:  */
 29: abstract class PresenterComponent extends Nette\ComponentModel\Container implements ISignalReceiver, IStatePersistent, \ArrayAccess
 30: {
 31:     /** @var array */
 32:     protected $params = array();
 33: 
 34: 
 35: 
 36:     /**
 37:      */
 38:     public function __construct(Nette\ComponentModel\IContainer $parent = NULL, $name = NULL)
 39:     {
 40:         $this->monitor('Nette\Application\UI\Presenter');
 41:         parent::__construct($parent, $name);
 42:     }
 43: 
 44: 
 45: 
 46:     /**
 47:      * Returns the presenter where this component belongs to.
 48:      * @param  bool   throw exception if presenter doesn't exist?
 49:      * @return Presenter|NULL
 50:      */
 51:     public function getPresenter($need = TRUE)
 52:     {
 53:         return $this->lookup('Nette\Application\UI\Presenter', $need);
 54:     }
 55: 
 56: 
 57: 
 58:     /**
 59:      * Returns a fully-qualified name that uniquely identifies the component
 60:      * within the presenter hierarchy.
 61:      * @return string
 62:      */
 63:     public function getUniqueId()
 64:     {
 65:         return $this->lookupPath('Nette\Application\UI\Presenter', TRUE);
 66:     }
 67: 
 68: 
 69: 
 70:     /**
 71:      * This method will be called when the component (or component's parent)
 72:      * becomes attached to a monitored object. Do not call this method yourself.
 73:      * @param  Nette\Application\IComponent
 74:      * @return void
 75:      */
 76:     protected function attached($presenter)
 77:     {
 78:         if ($presenter instanceof Presenter) {
 79:             $this->loadState($presenter->popGlobalParams($this->getUniqueId()));
 80:         }
 81:     }
 82: 
 83: 
 84: 
 85:     /**
 86:      * Calls public method if exists.
 87:      * @param  string
 88:      * @param  array
 89:      * @return bool  does method exist?
 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->invokeNamedArgs($this, $params);
 99:                 return TRUE;
100:             }
101:         }
102:         return FALSE;
103:     }
104: 
105: 
106: 
107:     /**
108:      * Checks for requirements such as authorization.
109:      * @return void
110:      */
111:     public function checkRequirements($element)
112:     {
113:     }
114: 
115: 
116: 
117:     /**
118:      * Access to reflection.
119:      * @return PresenterComponentReflection
120:      */
121:     public static function getReflection()
122:     {
123:         return new PresenterComponentReflection(get_called_class());
124:     }
125: 
126: 
127: 
128:     /********************* interface IStatePersistent ****************d*g**/
129: 
130: 
131: 
132:     /**
133:      * Loads state informations.
134:      * @param  array
135:      * @return void
136:      */
137:     public function loadState(array $params)
138:     {
139:         foreach ($this->getReflection()->getPersistentParams() as $nm => $meta) {
140:             if (isset($params[$nm])) { // ignore NULL values
141:                 if (isset($meta['def'])) {
142:                     if (is_array($params[$nm]) && !is_array($meta['def'])) {
143:                         $params[$nm] = $meta['def']; // prevents array to scalar conversion
144:                     } else {
145:                         settype($params[$nm], gettype($meta['def']));
146:                     }
147:                 }
148:                 $this->$nm = & $params[$nm];
149:             }
150:         }
151:         $this->params = $params;
152:     }
153: 
154: 
155: 
156:     /**
157:      * Saves state informations for next request.
158:      * @param  array
159:      * @param  PresenterComponentReflection (internal, used by Presenter)
160:      * @return void
161:      */
162:     public function saveState(array & $params, $reflection = NULL)
163:     {
164:         $reflection = $reflection === NULL ? $this->getReflection() : $reflection;
165:         foreach ($reflection->getPersistentParams() as $nm => $meta) {
166: 
167:             if (isset($params[$nm])) {
168:                 $val = $params[$nm]; // injected value
169: 
170:             } elseif (array_key_exists($nm, $params)) { // $params[$nm] === NULL
171:                 continue; // means skip
172: 
173:             } elseif (!isset($meta['since']) || $this instanceof $meta['since']) {
174:                 $val = $this->$nm; // object property value
175: 
176:             } else {
177:                 continue; // ignored parameter
178:             }
179: 
180:             if (is_object($val)) {
181:                 $class = get_class($this);
182:                 throw new Nette\InvalidStateException("Persistent parameter must be scalar or array, $class::\$$nm is " . gettype($val));
183: 
184:             } else {
185:                 if (isset($meta['def'])) {
186:                     settype($val, gettype($meta['def']));
187:                     if ($val === $meta['def']) {
188:                         $val = NULL;
189:                     }
190:                 } else {
191:                     if ((string) $val === '') {
192:                         $val = NULL;
193:                     }
194:                 }
195:                 $params[$nm] = $val;
196:             }
197:         }
198:     }
199: 
200: 
201: 
202:     /**
203:      * Returns component param.
204:      * If no key is passed, returns the entire array.
205:      * @param  string key
206:      * @param  mixed  default value
207:      * @return mixed
208:      */
209:     final public function getParam($name = NULL, $default = NULL)
210:     {
211:         if (func_num_args() === 0) {
212:             return $this->params;
213: 
214:         } elseif (isset($this->params[$name])) {
215:             return $this->params[$name];
216: 
217:         } else {
218:             return $default;
219:         }
220:     }
221: 
222: 
223: 
224:     /**
225:      * Returns a fully-qualified name that uniquely identifies the parameter.
226:      * @return string
227:      */
228:     final public function getParamId($name)
229:     {
230:         $uid = $this->getUniqueId();
231:         return $uid === '' ? $name : $uid . self::NAME_SEPARATOR . $name;
232:     }
233: 
234: 
235: 
236:     /**
237:      * Returns array of classes persistent parameters. They have public visibility and are non-static.
238:      * This default implementation detects persistent parameters by annotation @persistent.
239:      * @return array
240:      */
241:     public static function getPersistentParams()
242:     {
243:         $rc = new Nette\Reflection\ClassType(get_called_class());
244:         $params = array();
245:         foreach ($rc->getProperties(\ReflectionProperty::IS_PUBLIC) as $rp) {
246:             if (!$rp->isStatic() && $rp->hasAnnotation('persistent')) {
247:                 $params[] = $rp->getName();
248:             }
249:         }
250:         return $params;
251:     }
252: 
253: 
254: 
255:     /********************* interface ISignalReceiver ****************d*g**/
256: 
257: 
258: 
259:     /**
260:      * Calls signal handler method.
261:      * @param  string
262:      * @return void
263:      * @throws BadSignalException if there is not handler method
264:      */
265:     public function signalReceived($signal)
266:     {
267:         if (!$this->tryCall($this->formatSignalMethod($signal), $this->params)) {
268:             $class = get_class($this);
269:             throw new BadSignalException("There is no handler for signal '$signal' in class $class.");
270:         }
271:     }
272: 
273: 
274: 
275:     /**
276:      * Formats signal handler method name -> case sensitivity doesn't matter.
277:      * @param  string
278:      * @return string
279:      */
280:     public function formatSignalMethod($signal)
281:     {
282:         return $signal == NULL ? NULL : 'handle' . $signal; // intentionally ==
283:     }
284: 
285: 
286: 
287:     /********************* navigation ****************d*g**/
288: 
289: 
290: 
291:     /**
292:      * Generates URL to presenter, action or signal.
293:      * @param  string   destination in format "[[module:]presenter:]action" or "signal!" or "this"
294:      * @param  array|mixed
295:      * @return string
296:      * @throws InvalidLinkException
297:      */
298:     public function link($destination, $args = array())
299:     {
300:         if (!is_array($args)) {
301:             $args = func_get_args();
302:             array_shift($args);
303:         }
304: 
305:         try {
306:             return $this->getPresenter()->createRequest($this, $destination, $args, 'link');
307: 
308:         } catch (InvalidLinkException $e) {
309:             return $this->getPresenter()->handleInvalidLink($e);
310:         }
311:     }
312: 
313: 
314: 
315:     /**
316:      * Returns destination as Link object.
317:      * @param  string   destination in format "[[module:]presenter:]view" or "signal!"
318:      * @param  array|mixed
319:      * @return Link
320:      */
321:     public function lazyLink($destination, $args = array())
322:     {
323:         if (!is_array($args)) {
324:             $args = func_get_args();
325:             array_shift($args);
326:         }
327: 
328:         return new Link($this, $destination, $args);
329:     }
330: 
331: 
332: 
333:     /**
334:      * Determines whether it links to the current page.
335:      * @param  string   destination in format "[[module:]presenter:]action" or "signal!" or "this"
336:      * @param  array|mixed
337:      * @return bool
338:      * @throws InvalidLinkException
339:      */
340:     public function isLinkCurrent($destination = NULL, $args = array())
341:     {
342:         if ($destination !== NULL) {
343:             if (!is_array($args)) {
344:                 $args = func_get_args();
345:                 array_shift($args);
346:             }
347:             $this->link($destination, $args);
348:         }
349:         return $this->getPresenter()->getLastCreatedRequestFlag('current');
350:     }
351: 
352: 
353: 
354:     /**
355:      * Redirect to another presenter, action or signal.
356:      * @param  int      [optional] HTTP error code
357:      * @param  string   destination in format "[[module:]presenter:]view" or "signal!"
358:      * @param  array|mixed
359:      * @return void
360:      * @throws Nette\Application\AbortException
361:      */
362:     public function redirect($code, $destination = NULL, $args = array())
363:     {
364:         if (!is_numeric($code)) { // first parameter is optional
365:             $args = $destination;
366:             $destination = $code;
367:             $code = NULL;
368:         }
369: 
370:         if (!is_array($args)) {
371:             $args = func_get_args();
372:             if (is_numeric(array_shift($args))) {
373:                 array_shift($args);
374:             }
375:         }
376: 
377:         $presenter = $this->getPresenter();
378:         $presenter->redirectUrl($presenter->createRequest($this, $destination, $args, 'redirect'), $code);
379:     }
380: 
381: 
382: 
383:     /********************* interface \ArrayAccess ****************d*g**/
384: 
385: 
386: 
387:     /**
388:      * Adds the component to the container.
389:      * @param  string  component name
390:      * @param  Nette\ComponentModel\IComponent
391:      * @return void
392:      */
393:     final public function offsetSet($name, $component)
394:     {
395:         $this->addComponent($component, $name);
396:     }
397: 
398: 
399: 
400:     /**
401:      * Returns component specified by name. Throws exception if component doesn't exist.
402:      * @param  string  component name
403:      * @return Nette\ComponentModel\IComponent
404:      * @throws Nette\InvalidArgumentException
405:      */
406:     final public function offsetGet($name)
407:     {
408:         return $this->getComponent($name, TRUE);
409:     }
410: 
411: 
412: 
413:     /**
414:      * Does component specified by name exists?
415:      * @param  string  component name
416:      * @return bool
417:      */
418:     final public function offsetExists($name)
419:     {
420:         return $this->getComponent($name, FALSE) !== NULL;
421:     }
422: 
423: 
424: 
425:     /**
426:      * Removes component from the container.
427:      * @param  string  component name
428:      * @return void
429:      */
430:     final public function offsetUnset($name)
431:     {
432:         $component = $this->getComponent($name, FALSE);
433:         if ($component !== NULL) {
434:             $this->removeComponent($component);
435:         }
436:     }
437: 
438: }
439: 
Nette Framework 2.0beta1 API API documentation generated by ApiGen 2.3.0