Namespaces

  • Latte
    • Loaders
    • Macros
    • Runtime
  • Nette
    • Application
      • Responses
      • Routers
      • UI
    • Bridges
      • ApplicationLatte
      • ApplicationTracy
      • CacheLatte
      • DatabaseDI
      • DatabaseTracy
      • DITracy
      • FormsLatte
      • Framework
      • HttpTracy
      • SecurityTracy
    • Caching
      • Storages
    • ComponentModel
    • Database
      • Drivers
      • Reflection
      • Table
    • DI
      • Config
        • Adapters
      • Extensions
    • Diagnostics
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Latte
    • Loaders
    • Localization
    • Mail
    • Neon
    • PhpGenerator
    • Reflection
    • Security
    • Templating
    • Utils
  • NetteModule
  • none
  • Tracy

Classes

  • Control
  • Form
  • Multiplier
  • Presenter
  • PresenterComponent

Interfaces

  • IRenderable
  • ISignalReceiver
  • IStatePersistent
  • ITemplate
  • ITemplateFactory

Exceptions

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