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