Namespaces

  • 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

  • Control
  • Form
  • Multiplier
  • Presenter
  • PresenterComponent

Interfaces

  • 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 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:  * @property-read string $uniqueId
 29:  */
 30: abstract class PresenterComponent extends Nette\ComponentModel\Container implements ISignalReceiver, IStatePersistent, \ArrayAccess
 31: {
 32:     /** @var array */
 33:     protected $params = array();
 34: 
 35: 
 36: 
 37:     /**
 38:      */
 39:     public function __construct(Nette\ComponentModel\IContainer $parent = NULL, $name = NULL)
 40:     {
 41:         $this->monitor('Nette\Application\UI\Presenter');
 42:         parent::__construct($parent, $name);
 43:     }
 44: 
 45: 
 46: 
 47:     /**
 48:      * Returns the presenter where this component belongs to.
 49:      * @param  bool   throw exception if presenter doesn't exist?
 50:      * @return Presenter|NULL
 51:      */
 52:     public function getPresenter($need = TRUE)
 53:     {
 54:         return $this->lookup('Nette\Application\UI\Presenter', $need);
 55:     }
 56: 
 57: 
 58: 
 59:     /**
 60:      * Returns a fully-qualified name that uniquely identifies the component
 61:      * within the presenter hierarchy.
 62:      * @return string
 63:      */
 64:     public function getUniqueId()
 65:     {
 66:         return $this->lookupPath('Nette\Application\UI\Presenter', TRUE);
 67:     }
 68: 
 69: 
 70: 
 71:     /**
 72:      * This method will be called when the component (or component's parent)
 73:      * becomes attached to a monitored object. Do not call this method yourself.
 74:      * @param  Nette\ComponentModel\IComponent
 75:      * @return void
 76:      */
 77:     protected function attached($presenter)
 78:     {
 79:         if ($presenter instanceof Presenter) {
 80:             $this->loadState($presenter->popGlobalParameters($this->getUniqueId()));
 81:         }
 82:     }
 83: 
 84: 
 85: 
 86:     /**
 87:      * Calls public method if exists.
 88:      * @param  string
 89:      * @param  array
 90:      * @return bool  does method exist?
 91:      */
 92:     protected function tryCall($method, array $params)
 93:     {
 94:         $rc = $this->getReflection();
 95:         if ($rc->hasMethod($method)) {
 96:             $rm = $rc->getMethod($method);
 97:             if ($rm->isPublic() && !$rm->isAbstract() && !$rm->isStatic()) {
 98:                 $this->checkRequirements($rm);
 99:                 $rm->invokeArgs($this, $rc->combineArgs($rm, $params));
100:                 return TRUE;
101:             }
102:         }
103:         return FALSE;
104:     }
105: 
106: 
107: 
108:     /**
109:      * Checks for requirements such as authorization.
110:      * @return void
111:      */
112:     public function checkRequirements($element)
113:     {
114:     }
115: 
116: 
117: 
118:     /**
119:      * Access to reflection.
120:      * @return PresenterComponentReflection
121:      */
122:     public static function getReflection()
123:     {
124:         return new PresenterComponentReflection(get_called_class());
125:     }
126: 
127: 
128: 
129:     /********************* interface IStatePersistent ****************d*g**/
130: 
131: 
132: 
133:     /**
134:      * Loads state informations.
135:      * @param  array
136:      * @return void
137:      */
138:     public function loadState(array $params)
139:     {
140:         foreach ($this->getReflection()->getPersistentParams() as $nm => $meta) {
141:             if (isset($params[$nm])) { // ignore NULL values
142:                 if (isset($meta['def'])) {
143:                     if (is_array($params[$nm]) && !is_array($meta['def'])) {
144:                         $params[$nm] = $meta['def']; // prevents array to scalar conversion
145:                     } else {
146:                         settype($params[$nm], gettype($meta['def']));
147:                     }
148:                 }
149:                 $this->$nm = & $params[$nm];
150:             } else {
151:                 $params[$nm] = & $this->$nm;
152:             }
153:         }
154:         $this->params = $params;
155:     }
156: 
157: 
158: 
159:     /**
160:      * Saves state informations for next request.
161:      * @param  array
162:      * @param  PresenterComponentReflection (internal, used by Presenter)
163:      * @return void
164:      */
165:     public function saveState(array & $params, $reflection = NULL)
166:     {
167:         $reflection = $reflection === NULL ? $this->getReflection() : $reflection;
168:         foreach ($reflection->getPersistentParams() as $nm => $meta) {
169: 
170:             if (isset($params[$nm])) {
171:                 $val = $params[$nm]; // injected value
172: 
173:             } elseif (array_key_exists($nm, $params)) { // $params[$nm] === NULL
174:                 continue; // means skip
175: 
176:             } elseif (!isset($meta['since']) || $this instanceof $meta['since']) {
177:                 $val = $this->$nm; // object property value
178: 
179:             } else {
180:                 continue; // ignored parameter
181:             }
182: 
183:             if (is_object($val)) {
184:                 $class = get_class($this);
185:                 throw new Nette\InvalidStateException("Persistent parameter must be scalar or array, $class::\$$nm is " . gettype($val));
186: 
187:             } else {
188:                 if (isset($meta['def'])) {
189:                     settype($val, gettype($meta['def']));
190:                     if ($val === $meta['def']) {
191:                         $val = NULL;
192:                     }
193:                 } else {
194:                     if ((string) $val === '') {
195:                         $val = NULL;
196:                     }
197:                 }
198:                 $params[$nm] = $val;
199:             }
200:         }
201:     }
202: 
203: 
204: 
205:     /**
206:      * Returns component param.
207:      * If no key is passed, returns the entire array.
208:      * @param  string key
209:      * @param  mixed  default value
210:      * @return mixed
211:      */
212:     final public function getParameter($name = NULL, $default = NULL)
213:     {
214:         if (func_num_args() === 0) {
215:             return $this->params;
216: 
217:         } elseif (isset($this->params[$name])) {
218:             return $this->params[$name];
219: 
220:         } else {
221:             return $default;
222:         }
223:     }
224: 
225: 
226: 
227:     /**
228:      * Returns a fully-qualified name that uniquely identifies the parameter.
229:      * @return string
230:      */
231:     final public function getParameterId($name)
232:     {
233:         $uid = $this->getUniqueId();
234:         return $uid === '' ? $name : $uid . self::NAME_SEPARATOR . $name;
235:     }
236: 
237: 
238: 
239:     /** @deprecated */
240:     function getParam($name = NULL, $default = NULL)
241:     {
242:         //trigger_error(__METHOD__ . '() is deprecated; use getParameter() instead.', E_USER_WARNING);
243:         if (func_num_args() === 0) {
244:             return $this->params;
245:         } elseif (isset($this->params[$name])) {
246:             return $this->params[$name];
247:         } else {
248:             return $default;
249:         }
250:     }
251: 
252: 
253: 
254:     /** @deprecated */
255:     function getParamId($name)
256:     {
257:         trigger_error(__METHOD__ . '() is deprecated; use getParameterId() instead.', E_USER_WARNING);
258:         return $this->getParameterId($name);
259:     }
260: 
261: 
262: 
263:     /**
264:      * Returns array of classes persistent parameters. They have public visibility and are non-static.
265:      * This default implementation detects persistent parameters by annotation @persistent.
266:      * @return array
267:      */
268:     public static function getPersistentParams()
269:     {
270:         $rc = new Nette\Reflection\ClassType(get_called_class());
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 Nette\Application\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  Nette\ComponentModel\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 Nette\ComponentModel\IComponent
431:      * @throws Nette\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.0 API API documentation generated by ApiGen 2.7.0