%PDF- %PDF-
Direktori : /www/varak.net/losik.varak.net/vendor/nette/application/src/Application/UI/ |
Current File : //www/varak.net/losik.varak.net/vendor/nette/application/src/Application/UI/Component.php |
<?php /** * This file is part of the Nette Framework (https://nette.org) * Copyright (c) 2004 David Grudl (https://davidgrudl.com) */ declare(strict_types=1); namespace Nette\Application\UI; use Nette; /** * Component 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. * * @property-read Presenter $presenter * @property-read bool $linkCurrent */ abstract class Component extends Nette\ComponentModel\Container implements SignalReceiver, StatePersistent, \ArrayAccess { use Nette\ComponentModel\ArrayAccess; /** @var array<callable(self): void> Occurs when component is attached to presenter */ public $onAnchor = []; /** @var array */ protected $params = []; /** * Returns the presenter where this component belongs to. * @return Presenter */ public function getPresenter(): ?Presenter { if (func_num_args()) { trigger_error(__METHOD__ . '() parameter $throw is deprecated, use getPresenterIfExists()', E_USER_DEPRECATED); $throw = func_get_arg(0); } return $this->lookup(Presenter::class, $throw ?? true); } /** * Returns the presenter where this component belongs to. */ public function getPresenterIfExists(): ?Presenter { return $this->lookup(Presenter::class, false); } /** @deprecated */ public function hasPresenter(): bool { return (bool) $this->lookup(Presenter::class, false); } /** * Returns a fully-qualified name that uniquely identifies the component * within the presenter hierarchy. */ public function getUniqueId(): string { return $this->lookupPath(Presenter::class, true); } protected function createComponent(string $name): ?Nette\ComponentModel\IComponent { $res = parent::createComponent($name); if ($res && !$res instanceof SignalReceiver && !$res instanceof StatePersistent) { $type = get_class($res); trigger_error("It seems that component '$name' of type $type is not intended to be used in the Presenter.", E_USER_NOTICE); } return $res; } protected function validateParent(Nette\ComponentModel\IContainer $parent): void { parent::validateParent($parent); $this->monitor(Presenter::class, function (Presenter $presenter): void { $this->loadState($presenter->popGlobalParameters($this->getUniqueId())); Nette\Utils\Arrays::invoke($this->onAnchor, $this); }); } /** * Calls public method if exists. * @return bool does method exist? */ protected function tryCall(string $method, array $params): bool { $rc = $this->getReflection(); if (!$rc->hasMethod($method)) { return false; } elseif (!$rc->hasCallableMethod($method)) { throw new Nette\InvalidStateException('Method ' . Nette\Utils\Reflection::toString($rc->getMethod($method)) . ' is not callable.'); } $rm = $rc->getMethod($method); $this->checkRequirements($rm); try { $args = $rc->combineArgs($rm, $params); } catch (Nette\InvalidArgumentException $e) { throw new Nette\Application\BadRequestException($e->getMessage()); } $rm->invokeArgs($this, $args); return true; } /** * Checks for requirements such as authorization. */ public function checkRequirements($element): void { if ( $element instanceof \ReflectionMethod && substr($element->getName(), 0, 6) === 'handle' && !ComponentReflection::parseAnnotation($element, 'crossOrigin') && (PHP_VERSION_ID < 80000 || !$element->getAttributes(Nette\Application\Attributes\CrossOrigin::class)) && !$this->getPresenter()->getHttpRequest()->isSameSite() ) { $this->getPresenter()->detectedCsrf(); } } /** * Access to reflection. */ public static function getReflection(): ComponentReflection { return new ComponentReflection(static::class); } /********************* interface StatePersistent ****************d*g**/ /** * Loads state informations. */ public function loadState(array $params): void { $reflection = $this->getReflection(); foreach ($reflection->getPersistentParams() as $name => $meta) { if (isset($params[$name])) { // nulls are ignored if (!$reflection->convertType($params[$name], $meta['type'])) { throw new Nette\Application\BadRequestException(sprintf( "Value passed to persistent parameter '%s' in %s must be %s, %s given.", $name, $this instanceof Presenter ? 'presenter ' . $this->getName() : "component '{$this->getUniqueId()}'", $meta['type'], is_object($params[$name]) ? get_class($params[$name]) : gettype($params[$name]) )); } $this->$name = $params[$name]; } else { $params[$name] = $this->$name ?? null; } } $this->params = $params; } /** * Saves state informations for next request. */ public function saveState(array &$params): void { $this->getReflection()->saveState($this, $params); } /** * Returns component param. * @return mixed */ final public function getParameter(string $name) { if (func_num_args() > 1) { $default = func_get_arg(1); } return $this->params[$name] ?? $default ?? null; } /** * Returns component parameters. */ final public function getParameters(): array { return $this->params; } /** * Returns a fully-qualified name that uniquely identifies the parameter. */ final public function getParameterId(string $name): string { $uid = $this->getUniqueId(); return $uid === '' ? $name : $uid . self::NAME_SEPARATOR . $name; } /********************* interface SignalReceiver ****************d*g**/ /** * Calls signal handler method. * @throws BadSignalException if there is not handler method */ public function signalReceived(string $signal): void { if (!$this->tryCall($this->formatSignalMethod($signal), $this->params)) { $class = static::class; throw new BadSignalException("There is no handler for signal '$signal' in class $class."); } } /** * Formats signal handler method name -> case sensitivity doesn't matter. */ public static function formatSignalMethod(string $signal): string { return 'handle' . $signal; } /********************* navigation ****************d*g**/ /** * Generates URL to presenter, action or signal. * @param string $destination in format "[//] [[[module:]presenter:]action | signal! | this] [#fragment]" * @param array|mixed $args * @throws InvalidLinkException */ public function link(string $destination, $args = []): string { try { $args = func_num_args() < 3 && is_array($args) ? $args : array_slice(func_get_args(), 1); return $this->getPresenter()->createRequest($this, $destination, $args, 'link'); } catch (InvalidLinkException $e) { return $this->getPresenter()->handleInvalidLink($e); } } /** * Returns destination as Link object. * @param string $destination in format "[//] [[[module:]presenter:]action | signal! | this] [#fragment]" * @param array|mixed $args */ public function lazyLink(string $destination, $args = []): Link { $args = func_num_args() < 3 && is_array($args) ? $args : array_slice(func_get_args(), 1); return new Link($this, $destination, $args); } /** * Determines whether it links to the current page. * @param string $destination in format "[//] [[[module:]presenter:]action | signal! | this] [#fragment]" * @param array|mixed $args * @throws InvalidLinkException */ public function isLinkCurrent(?string $destination = null, $args = []): bool { if ($destination !== null) { $args = func_num_args() < 3 && is_array($args) ? $args : array_slice(func_get_args(), 1); $this->getPresenter()->createRequest($this, $destination, $args, 'test'); } return $this->getPresenter()->getLastCreatedRequestFlag('current'); } /** * Redirect to another presenter, action or signal. * @param string $destination in format "[//] [[[module:]presenter:]action | signal! | this] [#fragment]" * @param array|mixed $args * @return never * @throws Nette\Application\AbortException */ public function redirect(string $destination, $args = []): void { $args = func_num_args() < 3 && is_array($args) ? $args : array_slice(func_get_args(), 1); $presenter = $this->getPresenter(); $presenter->redirectUrl($presenter->createRequest($this, $destination, $args, 'redirect')); } /** * Permanently redirects to presenter, action or signal. * @param string $destination in format "[//] [[[module:]presenter:]action | signal! | this] [#fragment]" * @param array|mixed $args * @return never * @throws Nette\Application\AbortException */ public function redirectPermanent(string $destination, $args = []): void { $args = func_num_args() < 3 && is_array($args) ? $args : array_slice(func_get_args(), 1); $presenter = $this->getPresenter(); $presenter->redirectUrl( $presenter->createRequest($this, $destination, $args, 'redirect'), Nette\Http\IResponse::S301_MOVED_PERMANENTLY ); } /** * Throws HTTP error. * @throws Nette\Application\BadRequestException */ public function error(string $message = '', int $httpCode = Nette\Http\IResponse::S404_NOT_FOUND): void { throw new Nette\Application\BadRequestException($message, $httpCode); } } class_exists(PresenterComponent::class);