Packages

  • 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

  • NAppForm
  • NControl
  • NMultiplier
  • NPresenter
  • NPresenterComponent

Interfaces

  • IRenderable
  • ISignalReceiver
  • IStatePersistent

Exceptions

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