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
      • Table
    • DI
      • Config
        • Adapters
      • Extensions
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Loaders
    • Localization
    • Mail
    • Neon
    • PhpGenerator
    • Reflection
    • Security
    • Utils
  • none
  • Tracy
    • Bridges
      • Nette

Classes

  • Component
  • Control
  • Form
  • Link
  • Multiplier
  • Presenter

Interfaces

  • IRenderable
  • ISignalReceiver
  • IStatePersistent
  • ITemplate
  • ITemplateFactory

Exceptions

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