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

  • AppForm
  • Control
  • Multiplier
  • Presenter
  • PresenterComponent

Interfaces

  • IRenderable
  • ISignalReceiver
  • IStatePersistent

Exceptions

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