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:         $reflection = $this->getReflection();
141:         foreach ($reflection->getPersistentParams() as $name => $meta) {
142:             if (isset($params[$name])) { // NULLs are ignored
143:                 $type = gettype($meta['def'] === NULL ? $params[$name] : $meta['def']); // compatible with 2.0.x
144:                 if (!$reflection->convertType($params[$name], $type)) {
145:                     throw new Nette\Application\BadRequestException("Invalid value for persistent parameter '$name' in '{$this->getName()}', expected " . ($type === 'NULL' ? 'scalar' : $type) . ".");
146:                 }
147:                 $this->$name = & $params[$name];
148:             } else {
149:                 $params[$name] = & $this->$name;
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 $name => $meta) {
167: 
168:             if (isset($params[$name])) {
169:                 // injected value
170: 
171:             } elseif (array_key_exists($name, $params)) { // NULLs are skipped
172:                 continue;
173: 
174:             } elseif (!isset($meta['since']) || $this instanceof $meta['since']) {
175:                 $params[$name] = $this->$name; // object property value
176: 
177:             } else {
178:                 continue; // ignored parameter
179:             }
180: 
181:             $type = gettype($meta['def'] === NULL ? $params[$name] : $meta['def']); // compatible with 2.0.x
182:             if (!PresenterComponentReflection::convertType($params[$name], $type)) {
183:                 throw new InvalidLinkException("Invalid value for persistent parameter '$name' in '{$this->getName()}', expected " . ($type === 'NULL' ? 'scalar' : $type) . ".");
184:             }
185: 
186:             if ($params[$name] === $meta['def'] || ($meta['def'] === NULL && is_scalar($params[$name]) && (string) $params[$name] === '')) {
187:                 $params[$name] = NULL; // value transmit is unnecessary
188:             }
189:         }
190:     }
191: 
192: 
193: 
194:     /**
195:      * Returns component param.
196:      * If no key is passed, returns the entire array.
197:      * @param  string key
198:      * @param  mixed  default value
199:      * @return mixed
200:      */
201:     final public function getParameter($name = NULL, $default = NULL)
202:     {
203:         if (func_num_args() === 0) {
204:             return $this->params;
205: 
206:         } elseif (isset($this->params[$name])) {
207:             return $this->params[$name];
208: 
209:         } else {
210:             return $default;
211:         }
212:     }
213: 
214: 
215: 
216:     /**
217:      * Returns a fully-qualified name that uniquely identifies the parameter.
218:      * @param  string
219:      * @return string
220:      */
221:     final public function getParameterId($name)
222:     {
223:         $uid = $this->getUniqueId();
224:         return $uid === '' ? $name : $uid . self::NAME_SEPARATOR . $name;
225:     }
226: 
227: 
228: 
229:     /** @deprecated */
230:     function getParam($name = NULL, $default = NULL)
231:     {
232:         //trigger_error(__METHOD__ . '() is deprecated; use getParameter() instead.', E_USER_WARNING);
233:         return func_num_args() ? $this->getParameter($name, $default) : $this->getParameter();
234:     }
235: 
236: 
237: 
238:     /** @deprecated */
239:     function getParamId($name)
240:     {
241:         trigger_error(__METHOD__ . '() is deprecated; use getParameterId() instead.', E_USER_WARNING);
242:         return $this->getParameterId($name);
243:     }
244: 
245: 
246: 
247:     /**
248:      * Returns array of classes persistent parameters. They have public visibility and are non-static.
249:      * This default implementation detects persistent parameters by annotation @persistent.
250:      * @return array
251:      */
252:     public static function getPersistentParams()
253:     {
254:         $rc = new Nette\Reflection\ClassType(get_called_class());
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:     /********************* interface ISignalReceiver ****************d*g**/
267: 
268: 
269: 
270:     /**
271:      * Calls signal handler method.
272:      * @param  string
273:      * @return void
274:      * @throws BadSignalException if there is not handler method
275:      */
276:     public function signalReceived($signal)
277:     {
278:         if (!$this->tryCall($this->formatSignalMethod($signal), $this->params)) {
279:             $class = get_class($this);
280:             throw new BadSignalException("There is no handler for signal '$signal' in class $class.");
281:         }
282:     }
283: 
284: 
285: 
286:     /**
287:      * Formats signal handler method name -> case sensitivity doesn't matter.
288:      * @param  string
289:      * @return string
290:      */
291:     public function formatSignalMethod($signal)
292:     {
293:         return $signal == NULL ? NULL : 'handle' . $signal; // intentionally ==
294:     }
295: 
296: 
297: 
298:     /********************* navigation ****************d*g**/
299: 
300: 
301: 
302:     /**
303:      * Generates URL to presenter, action or signal.
304:      * @param  string   destination in format "[[module:]presenter:]action" or "signal!" or "this"
305:      * @param  array|mixed
306:      * @return string
307:      * @throws InvalidLinkException
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 (InvalidLinkException $e) {
320:             return $this->getPresenter()->handleInvalidLink($e);
321:         }
322:     }
323: 
324: 
325: 
326:     /**
327:      * Returns destination as Link object.
328:      * @param  string   destination in format "[[module:]presenter:]view" or "signal!"
329:      * @param  array|mixed
330:      * @return Link
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 Link($this, $destination, $args);
340:     }
341: 
342: 
343: 
344:     /**
345:      * Determines whether it links to the current page.
346:      * @param  string   destination in format "[[module:]presenter:]action" or "signal!" or "this"
347:      * @param  array|mixed
348:      * @return bool
349:      * @throws InvalidLinkException
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->link($destination, $args);
359:         }
360:         return $this->getPresenter()->getLastCreatedRequestFlag('current');
361:     }
362: 
363: 
364: 
365:     /**
366:      * Redirect to another presenter, action or signal.
367:      * @param  int      [optional] HTTP error code
368:      * @param  string   destination in format "[[module:]presenter:]view" or "signal!"
369:      * @param  array|mixed
370:      * @return void
371:      * @throws Nette\Application\AbortException
372:      */
373:     public function redirect($code, $destination = NULL, $args = array())
374:     {
375:         if (!is_numeric($code)) { // first parameter is optional
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:     /********************* interface \ArrayAccess ****************d*g**/
395: 
396: 
397: 
398:     /**
399:      * Adds the component to the container.
400:      * @param  string  component name
401:      * @param  Nette\ComponentModel\IComponent
402:      * @return void
403:      */
404:     final public function offsetSet($name, $component)
405:     {
406:         $this->addComponent($component, $name);
407:     }
408: 
409: 
410: 
411:     /**
412:      * Returns component specified by name. Throws exception if component doesn't exist.
413:      * @param  string  component name
414:      * @return Nette\ComponentModel\IComponent
415:      * @throws Nette\InvalidArgumentException
416:      */
417:     final public function offsetGet($name)
418:     {
419:         return $this->getComponent($name, TRUE);
420:     }
421: 
422: 
423: 
424:     /**
425:      * Does component specified by name exists?
426:      * @param  string  component name
427:      * @return bool
428:      */
429:     final public function offsetExists($name)
430:     {
431:         return $this->getComponent($name, FALSE) !== NULL;
432:     }
433: 
434: 
435: 
436:     /**
437:      * Removes component from the container.
438:      * @param  string  component name
439:      * @return void
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: 
Nette Framework 2.0.4 API API documentation generated by ApiGen 2.7.0