ACC SHELL
<?php
/**
* This file is part of the Nette Framework (http://nette.org)
* Copyright (c) 2004 David Grudl (http://davidgrudl.com)
* @package Nette\Application\UI
*/
/**
* PresenterComponent is the base class for all Presenter components.
*
* Components are persistent objects located on a presenter. They have ability to own
* other child components, and interact with user. Components have properties
* for storing their status, and responds to user command.
*
* @author David Grudl
*
* @property-read NPresenter $presenter
* @property-read string $uniqueId
* @package Nette\Application\UI
*/
abstract class NPresenterComponent extends NComponentContainer implements ISignalReceiver, IStatePersistent, ArrayAccess
{
/** @var array */
protected $params = array();
/**
* Returns the presenter where this component belongs to.
* @param bool throw exception if presenter doesn't exist?
* @return NPresenter|NULL
*/
public function getPresenter($need = TRUE)
{
return $this->lookup('NPresenter', $need);
}
/**
* Returns a fully-qualified name that uniquely identifies the component
* within the presenter hierarchy.
* @return string
*/
public function getUniqueId()
{
return $this->lookupPath('NPresenter', TRUE);
}
/**
* This method will be called when the component (or component's parent)
* becomes attached to a monitored object. Do not call this method yourself.
* @param IComponent
* @return void
*/
protected function attached($presenter)
{
if ($presenter instanceof NPresenter) {
$this->loadState($presenter->popGlobalParameters($this->getUniqueId()));
}
}
/**
* @return void
*/
protected function validateParent(IComponentContainer $parent)
{
parent::validateParent($parent);
$this->monitor('NPresenter');
}
/**
* Calls public method if exists.
* @param string
* @param array
* @return bool does method exist?
*/
protected function tryCall($method, array $params)
{
$rc = $this->getReflection();
if ($rc->hasMethod($method)) {
$rm = $rc->getMethod($method);
if ($rm->isPublic() && !$rm->isAbstract() && !$rm->isStatic()) {
$this->checkRequirements($rm);
$rm->invokeArgs($this, $rc->combineArgs($rm, $params));
return TRUE;
}
}
return FALSE;
}
/**
* Checks for requirements such as authorization.
* @return void
*/
public function checkRequirements($element)
{
}
/**
* Access to reflection.
* @return NPresenterComponentReflection
*/
public function getReflection()
{
return new NPresenterComponentReflection($this);
}
/********************* interface IStatePersistent ****************d*g**/
/**
* Loads state informations.
* @param array
* @return void
*/
public function loadState(array $params)
{
$reflection = $this->getReflection();
foreach ($reflection->getPersistentParams() as $name => $meta) {
if (isset($params[$name])) { // NULLs are ignored
$type = gettype($meta['def'] === NULL ? $params[$name] : $meta['def']); // compatible with 2.0.x
if (!$reflection->convertType($params[$name], $type)) {
throw new NBadRequestException("Invalid value for persistent parameter '$name' in '{$this->getName()}', expected " . ($type === 'NULL' ? 'scalar' : $type) . ".");
}
$this->$name = & $params[$name];
} else {
$params[$name] = & $this->$name;
}
}
$this->params = $params;
}
/**
* Saves state informations for next request.
* @param array
* @param NPresenterComponentReflection (internal, used by Presenter)
* @return void
*/
public function saveState(array & $params, $reflection = NULL)
{
$reflection = $reflection === NULL ? $this->getReflection() : $reflection;
foreach ($reflection->getPersistentParams() as $name => $meta) {
if (isset($params[$name])) {
// injected value
} elseif (array_key_exists($name, $params)) { // NULLs are skipped
continue;
} elseif (!isset($meta['since']) || $this instanceof $meta['since']) {
$params[$name] = $this->$name; // object property value
} else {
continue; // ignored parameter
}
$type = gettype($meta['def'] === NULL ? $params[$name] : $meta['def']); // compatible with 2.0.x
if (!NPresenterComponentReflection::convertType($params[$name], $type)) {
throw new NInvalidLinkException("Invalid value for persistent parameter '$name' in '{$this->getName()}', expected " . ($type === 'NULL' ? 'scalar' : $type) . ".");
}
if ($params[$name] === $meta['def'] || ($meta['def'] === NULL && is_scalar($params[$name]) && (string) $params[$name] === '')) {
$params[$name] = NULL; // value transmit is unnecessary
}
}
}
/**
* Returns component param.
* If no key is passed, returns the entire array.
* @param string key
* @param mixed default value
* @return mixed
*/
public function getParameter($name = NULL, $default = NULL)
{
if (func_num_args() === 0) {
return $this->params;
} elseif (isset($this->params[$name])) {
return $this->params[$name];
} else {
return $default;
}
}
/**
* Returns a fully-qualified name that uniquely identifies the parameter.
* @param string
* @return string
*/
public function getParameterId($name)
{
$uid = $this->getUniqueId();
return $uid === '' ? $name : $uid . self::NAME_SEPARATOR . $name;
}
/** @deprecated */
function getParam($name = NULL, $default = NULL)
{
//trigger_error(__METHOD__ . '() is deprecated; use getParameter() instead.', E_USER_WARNING);
return func_num_args() ? $this->getParameter($name, $default) : $this->getParameter();
}
/** @deprecated */
function getParamId($name)
{
trigger_error(__METHOD__ . '() is deprecated; use getParameterId() instead.', E_USER_WARNING);
return $this->getParameterId($name);
}
/**
* Returns array of classes persistent parameters. They have public visibility and are non-static.
* This default implementation detects persistent parameters by annotation @persistent.
* @return array
*/
public static function getPersistentParams()
{
$rc = new NClassReflection(func_get_arg(0));
$params = array();
foreach ($rc->getProperties(ReflectionProperty::IS_PUBLIC) as $rp) {
if (!$rp->isStatic() && $rp->hasAnnotation('persistent')) {
$params[] = $rp->getName();
}
}
return $params;
}
/********************* interface ISignalReceiver ****************d*g**/
/**
* Calls signal handler method.
* @param string
* @return void
* @throws NBadSignalException if there is not handler method
*/
public function signalReceived($signal)
{
if (!$this->tryCall($this->formatSignalMethod($signal), $this->params)) {
$class = get_class($this);
throw new NBadSignalException("There is no handler for signal '$signal' in class $class.");
}
}
/**
* Formats signal handler method name -> case sensitivity doesn't matter.
* @param string
* @return string
*/
public function formatSignalMethod($signal)
{
return $signal == NULL ? NULL : 'handle' . $signal; // intentionally ==
}
/********************* navigation ****************d*g**/
/**
* Generates URL to presenter, action or signal.
* @param string destination in format "[[module:]presenter:]action" or "signal!" or "this"
* @param array|mixed
* @return string
* @throws NInvalidLinkException
*/
public function link($destination, $args = array())
{
try {
$_args=func_get_args(); return $this->getPresenter()->createRequest($this, $destination, is_array($args) ? $args : array_slice($_args, 1), 'link');
} catch (NInvalidLinkException $e) {
return $this->getPresenter()->handleInvalidLink($e);
}
}
/**
* Returns destination as Link object.
* @param string destination in format "[[module:]presenter:]view" or "signal!"
* @param array|mixed
* @return NLink
*/
public function lazyLink($destination, $args = array())
{
$_args=func_get_args(); return new NLink($this, $destination, is_array($args) ? $args : array_slice($_args, 1));
}
/**
* Determines whether it links to the current page.
* @param string destination in format "[[module:]presenter:]action" or "signal!" or "this"
* @param array|mixed
* @return bool
* @throws NInvalidLinkException
*/
public function isLinkCurrent($destination = NULL, $args = array())
{
if ($destination !== NULL) {
$_args=func_get_args(); $this->getPresenter()->createRequest($this, $destination, is_array($args) ? $args : array_slice($_args, 1), 'test');
}
return $this->getPresenter()->getLastCreatedRequestFlag('current');
}
/**
* Redirect to another presenter, action or signal.
* @param int [optional] HTTP error code
* @param string destination in format "[[module:]presenter:]view" or "signal!"
* @param array|mixed
* @return void
* @throws NAbortException
*/
public function redirect($code, $destination = NULL, $args = array())
{
if (!is_numeric($code)) { // first parameter is optional
$args = $destination;
$destination = $code;
$code = NULL;
}
if (!is_array($args)) {
$args = array_slice(func_get_args(), is_numeric($code) ? 2 : 1);
}
$presenter = $this->getPresenter();
$presenter->redirectUrl($presenter->createRequest($this, $destination, $args, 'redirect'), $code);
}
/********************* interface ArrayAccess ****************d*g**/
/**
* Adds the component to the container.
* @param string component name
* @param IComponent
* @return void
*/
public function offsetSet($name, $component)
{
$this->addComponent($component, $name);
}
/**
* Returns component specified by name. Throws exception if component doesn't exist.
* @param string component name
* @return IComponent
* @throws InvalidArgumentException
*/
public function offsetGet($name)
{
return $this->getComponent($name, TRUE);
}
/**
* Does component specified by name exists?
* @param string component name
* @return bool
*/
public function offsetExists($name)
{
return $this->getComponent($name, FALSE) !== NULL;
}
/**
* Removes component from the container.
* @param string component name
* @return void
*/
public function offsetUnset($name)
{
$component = $this->getComponent($name, FALSE);
if ($component !== NULL) {
$this->removeComponent($component);
}
}
}
ACC SHELL 2018