Packages

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

Classes

  • AppForm
  • Control
  • Presenter
  • PresenterComponent

Interfaces

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