Namespaces

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

Classes

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