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