예제 #1
0
 /**
  * Creates link.
  *
  * Destination syntax:
  *  - 'Presenter:action' - creates relative link
  *  - '//Presenter:action' - creates absolute link
  *  - 'Presenter:action#fragment' - may contain optional fragment
  *
  * @param  string 'Presenter:action' (creates relative link) or '//Presenter:action' (creates absolute link)
  * @param  array
  * @return string
  * @throws InvalidLinkException if router returns NULL
  */
 public function link($destination, array $params = array())
 {
     if (($pos = strrpos($destination, '#')) !== FALSE) {
         $fragment = substr($destination, $pos);
         $destination = substr($destination, 0, $pos);
     } else {
         $fragment = '';
     }
     if (strncmp($destination, '//', 2) === 0) {
         $absoluteUrl = TRUE;
         $destination = substr($destination, 2);
     } else {
         $absoluteUrl = FALSE;
     }
     $pos = strrpos($destination, ':');
     $presenter = substr($destination, 0, $pos);
     if ($pos + 1 < strlen($destination)) {
         $params['action'] = substr($destination, $pos + 1);
     }
     $request = new Nette\Application\Request($presenter, 'GET', $params);
     $url = $this->router->constructUrl($request, $this->refUrl);
     if ($url === NULL) {
         throw new InvalidLinkException("Router failed to create link to '{$destination}'.");
     }
     if (!$absoluteUrl && strncmp($url, $this->refUrlHost, strlen($this->refUrlHost)) === 0) {
         $url = substr($url, strlen($this->refUrlHost));
     }
     if ($fragment) {
         $url .= $fragment;
     }
     return $url;
 }
 /**
  * Generates URL to presenter.
  * @param  string   destination in format "[[[module:]presenter:]action] [#fragment]"
  * @return string
  * @throws UI\InvalidLinkException
  */
 public function link($dest, array $params = array())
 {
     if (!preg_match('~^([\\w:]+):(\\w*+)(#.*)?()\\z~', $dest, $m)) {
         throw new UI\InvalidLinkException("Invalid link destination '{$dest}'.");
     }
     list(, $presenter, $action, $frag) = $m;
     try {
         $class = $this->presenterFactory ? $this->presenterFactory->getPresenterClass($presenter) : NULL;
     } catch (InvalidPresenterException $e) {
         throw new UI\InvalidLinkException($e->getMessage(), NULL, $e);
     }
     if (is_subclass_of($class, 'Nette\\Application\\UI\\Presenter')) {
         if ($action === '') {
             $action = UI\Presenter::DEFAULT_ACTION;
         }
         if (method_exists($class, $method = $class::formatActionMethod($action)) || method_exists($class, $method = $class::formatRenderMethod($action))) {
             UI\Presenter::argsToParams($class, $method, $params);
         }
     }
     if ($action !== '') {
         $params[UI\Presenter::ACTION_KEY] = $action;
     }
     $url = $this->router->constructUrl(new Request($presenter, NULL, $params), $this->refUrl);
     if ($url === NULL) {
         unset($params[UI\Presenter::ACTION_KEY]);
         $params = urldecode(http_build_query($params, NULL, ', '));
         throw new UI\InvalidLinkException("No route for {$dest}({$params})");
     }
     return $url . $frag;
 }
예제 #3
0
 /**
  * {@inheritdoc}
  */
 public function getResourceId()
 {
     $refUrl = $this->httpRequest->getUrl();
     $url = $this->router->constructUrl($this->request, $refUrl);
     if ($url === NULL) {
         throw new \Nette\Application\UI\InvalidLinkException();
     }
     $hostUrl = $refUrl->getHostUrl() . '/';
     if (strncmp($url, $hostUrl, strlen($hostUrl)) === 0) {
         $url = substr($url, strlen($hostUrl) - 1);
     }
     return $url;
 }
예제 #4
0
	/**
	 * @return Nette\Application\IResponse
	 */
	public function run(Application\Request $request)
	{
		$this->request = $request;

		if ($this->httpRequest && $this->router && !$this->httpRequest->isAjax() && ($request->isMethod('get') || $request->isMethod('head'))) {
			$refUrl = clone $this->httpRequest->getUrl();
			$url = $this->router->constructUrl($request, $refUrl->setPath($refUrl->getScriptPath()));
			if ($url !== NULL && !$this->httpRequest->getUrl()->isEqual($url)) {
				return new Responses\RedirectResponse($url, Http\IResponse::S301_MOVED_PERMANENTLY);
			}
		}

		$params = $request->getParameters();
		if (!isset($params['callback'])) {
			throw new Application\BadRequestException('Parameter callback is missing.');
		}
		$params['presenter'] = $this;
		$callback = $params['callback'];
		$reflection = Nette\Utils\Callback::toReflection(Nette\Utils\Callback::check($callback));
		$params = Application\UI\PresenterComponentReflection::combineArgs($reflection, $params);

		if ($this->context) {
			foreach ($reflection->getParameters() as $param) {
				if ($param->getClassName()) {
					unset($params[$param->getPosition()]);
				}
			}

			$params = Nette\DI\Helpers::autowireArguments($reflection, $params, $this->context);
			$params['presenter'] = $this;
		}

		$response = call_user_func_array($callback, $params);

		if (is_string($response)) {
			$response = array($response, array());
		}
		if (is_array($response)) {
			list($templateSource, $templateParams) = $response;
			$response = $this->createTemplate()->setParameters($templateParams);
			if (!$templateSource instanceof \SplFileInfo) {
				$response->getLatte()->setLoader(new Latte\Loaders\StringLoader);
			}
			$response->setFile($templateSource);
		}
		if ($response instanceof Application\UI\ITemplate) {
			return new Responses\TextResponse($response);
		} else {
			return $response;
		}
	}
 /**
  * Restores request from session.
  * @param string $key
  */
 public function redirectToRequest($key)
 {
     $request = $this->requestStorage->loadRequest($key);
     if (!$request) {
         return;
     }
     $parameters = $request->getParameters();
     $parameters[Presenter::FLASH_KEY] = $this->getParameter(Presenter::FLASH_KEY);
     $parameters[RequestStorage::REQUEST_KEY] = $key;
     $request->setParameters($parameters);
     $refUrl = new Url($this->httpRequest->getUrl());
     $refUrl->setPath($this->httpRequest->getUrl()->getScriptPath());
     $url = $this->router->constructUrl($request, $refUrl);
     $this->redirectUrl($url);
 }
예제 #6
0
 /**
  * @param \Nette\Application\Request $request
  * @return \Nette\Application\IResponse
  * @throws \Nette\Application\BadRequestException
  */
 public function run(Application\Request $request)
 {
     $this->request = $request;
     if ($this->httpRequest && $this->router && !$this->httpRequest->isAjax() && ($request->isMethod('get') || $request->isMethod('head'))) {
         $refUrl = clone $this->httpRequest->getUrl();
         $url = $this->router->constructUrl($request, $refUrl->setPath($refUrl->getScriptPath()));
         if ($url !== NULL && !$this->httpRequest->getUrl()->isEqual($url)) {
             return new Responses\RedirectResponse($url, Http\IResponse::S301_MOVED_PERMANENTLY);
         }
     }
     $params = $request->getParameters();
     if (!isset($params['id'])) {
         throw new Application\BadRequestException('Parameter id is missing.');
     }
     if (NULL === ($item = $this->context->getService('webloader.cache')->getItem(\Nette\Utils\Strings::webalize($params['id'])))) {
         return new Responses\TextResponse('');
     }
     return new \Lohini\WebLoader\WebLoaderResponse($item[WebLoader::CONTENT], $item[WebLoader::CONTENT_TYPE], $item[WebLoader::ETAG]);
 }
예제 #7
0
 /**
  * URL factory.
  *
  * @param string $destination in format "[module:]presenter:action"
  * @param array $args array of arguments
  * @return string URL
  * @throws Application\UI\InvalidLinkException
  */
 public function link($destination, array $args = array())
 {
     $a = strpos($destination, '#');
     if ($a === FALSE) {
         $fragment = '';
     } else {
         $fragment = substr($destination, $a);
         $destination = substr($destination, 0, $a);
     }
     $a = strpos($destination, '?');
     if ($a !== FALSE) {
         parse_str(substr($destination, $a + 1), $args);
         // requires disabled magic quotes
         $destination = substr($destination, 0, $a);
     }
     $a = strpos($destination, '//');
     if ($a !== FALSE) {
         $destination = substr($destination, $a + 2);
     }
     if ($destination == NULL) {
         // intentionally ==
         throw new Application\UI\InvalidLinkException("Destination must be non-empty string.");
     }
     $a = strrpos($destination, ':');
     $action = (string) substr($destination, $a + 1);
     $presenter = substr($destination, 0, $a);
     if ($presenter[0] == ":") {
         $presenter = substr($presenter, 1);
     }
     if (!$action) {
         $action = 'default';
     }
     $args[Application\UI\Presenter::ACTION_KEY] = $action;
     $request = new Application\Request($presenter, Application\Request::FORWARD, $args, array(), array());
     $url = $this->router->constructUrl($request, $this->refUrl);
     if ($url === NULL) {
         unset($args[Application\UI\Presenter::ACTION_KEY]);
         $params = urldecode(http_build_query($args, NULL, ', '));
         throw new Application\UI\InvalidLinkException("No route for {$presenter}:{$action}({$params})");
     }
     return $url . $fragment;
 }
예제 #8
0
 /**
  * URL factory.
  *
  * @param string $destination in format "[module:]presenter:action"
  * @param array $args array of arguments
  * @return string URL
  * @throws InvalidLinkException
  */
 public function link($destination, array $args = [])
 {
     if (!$this->refUrl) {
         throw new InvalidStateException("Reference URL is not set.");
     }
     // 1) fragment
     $a = strpos($destination, '#');
     if ($a === FALSE) {
         $fragment = '';
     } else {
         $fragment = substr($destination, $a);
         $destination = substr($destination, 0, $a);
     }
     // 2) ?query syntax
     $a = strpos($destination, '?');
     if ($a !== FALSE) {
         parse_str(substr($destination, $a + 1), $args);
         // requires disabled magic quotes
         $destination = substr($destination, 0, $a);
     }
     // 3) URL scheme
     $a = strpos($destination, '//');
     if ($a !== FALSE) {
         $destination = substr($destination, $a + 2);
     }
     if ($destination == NULL) {
         // intentionally ==
         throw new InvalidLinkException("Destination must be non-empty string.");
     }
     // 5) presenter: action
     $a = strrpos($destination, ':');
     $action = (string) substr($destination, $a + 1);
     $presenter = substr($destination, 0, $a);
     if ($presenter[0] == ":") {
         $presenter = substr($presenter, 1);
     }
     if (!$action) {
         $action = 'default';
     }
     // ADD ACTION
     $args[Presenter::ACTION_KEY] = $action;
     $request = new Application\Request($presenter, Application\Request::FORWARD, $args, [], []);
     // CONSTRUCT URL
     $url = $this->router->constructUrl($request, $this->refUrl);
     if ($url === NULL) {
         unset($args[Presenter::ACTION_KEY]);
         $params = urldecode(http_build_query($args, NULL, ', '));
         throw new InvalidLinkException("No route for {$presenter}:{$action}({$params})");
     }
     return $url . $fragment;
 }
예제 #9
0
 /**
  * Generates URL to presenter.
  * @param  string   destination in format "[[[module:]presenter:]action] [#fragment]"
  * @return string
  * @throws UI\InvalidLinkException
  */
 public function link($dest, array $params = [])
 {
     if (!preg_match('~^([\\w:]+):(\\w*+)(#.*)?()\\z~', $dest, $m)) {
         throw new UI\InvalidLinkException("Invalid link destination '{$dest}'.");
     }
     list(, $presenter, $action, $frag) = $m;
     try {
         $class = $this->presenterFactory ? $this->presenterFactory->getPresenterClass($presenter) : NULL;
     } catch (InvalidPresenterException $e) {
         throw new UI\InvalidLinkException($e->getMessage(), NULL, $e);
     }
     if (is_subclass_of($class, UI\Presenter::class)) {
         if ($action === '') {
             $action = UI\Presenter::DEFAULT_ACTION;
         }
         if (method_exists($class, $method = $class::formatActionMethod($action)) || method_exists($class, $method = $class::formatRenderMethod($action))) {
             UI\Presenter::argsToParams($class, $method, $params, [], $missing);
             if ($missing) {
                 $rp = $missing[0];
                 throw new UI\InvalidLinkException("Missing parameter \${$rp->getName()} required by {$rp->getDeclaringClass()->getName()}::{$rp->getDeclaringFunction()->getName()}()");
             }
         } elseif (array_key_exists(0, $params)) {
             throw new UI\InvalidLinkException("Unable to pass parameters to action '{$presenter}:{$action}', missing corresponding method.");
         }
     }
     if ($action !== '') {
         $params[UI\Presenter::ACTION_KEY] = $action;
     }
     $url = $this->router->constructUrl(new Request($presenter, NULL, $params), $this->refUrl);
     if ($url === NULL) {
         unset($params[UI\Presenter::ACTION_KEY]);
         $params = urldecode(http_build_query($params, NULL, ', '));
         throw new UI\InvalidLinkException("No route for {$dest}({$params})");
     }
     return $url . $frag;
 }
예제 #10
0
 /**
  * @param Application\Request $request
  *
  * @return Application\IResponse
  *
  * @throws Application\BadRequestException
  */
 public function run(Application\Request $request)
 {
     $this->request = $request;
     if ($this->httpRequest && $this->router && !$this->httpRequest->isAjax() && ($request->isMethod('get') || $request->isMethod('head'))) {
         $refUrl = clone $this->httpRequest->getUrl();
         $url = $this->router->constructUrl($request, $refUrl->setPath($refUrl->getScriptPath()));
         if ($url !== NULL && !$this->httpRequest->getUrl()->isEqual($url)) {
             return new Application\Responses\RedirectResponse($url, Http\IResponse::S301_MOVED_PERMANENTLY);
         }
     }
     $params = $request->getParameters();
     if (!isset($params['action'])) {
         throw new Application\BadRequestException('Parameter action is missing.');
     }
     if (!isset($params['id'])) {
         throw new Application\BadRequestException('Parameter id is missing.');
     }
     // calls $this->action<Action>()
     if (!($response = $this->tryCall(Application\UI\Presenter::formatActionMethod(Utils\Strings::capitalize($params['action'])), $params))) {
         throw new Application\BadRequestException('Action not callable.');
     }
     return $response;
 }
예제 #11
0
 /**
  * Request/URL factory.
  * @param  PresenterComponent  base
  * @param  string   destination in format "[//] [[[module:]presenter:]action | signal! | this] [#fragment]"
  * @param  array    array of arguments
  * @param  string   forward|redirect|link
  * @return string   URL
  * @throws InvalidLinkException
  * @internal
  */
 protected function createRequest($component, $destination, array $args, $mode)
 {
     // note: createRequest supposes that saveState(), run() & tryCall() behaviour is final
     $this->lastCreatedRequest = $this->lastCreatedRequestFlag = NULL;
     // PARSE DESTINATION
     // 1) fragment
     $a = strpos($destination, '#');
     if ($a === FALSE) {
         $fragment = '';
     } else {
         $fragment = substr($destination, $a);
         $destination = substr($destination, 0, $a);
     }
     // 2) ?query syntax
     $a = strpos($destination, '?');
     if ($a !== FALSE) {
         parse_str(substr($destination, $a + 1), $args);
         $destination = substr($destination, 0, $a);
     }
     // 3) URL scheme
     $a = strpos($destination, '//');
     if ($a === FALSE) {
         $scheme = FALSE;
     } else {
         $scheme = substr($destination, 0, $a);
         $destination = substr($destination, $a + 2);
     }
     // 4) signal or empty
     if (!$component instanceof self || substr($destination, -1) === '!') {
         $signal = rtrim($destination, '!');
         $a = strrpos($signal, ':');
         if ($a !== FALSE) {
             $component = $component->getComponent(strtr(substr($signal, 0, $a), ':', '-'));
             $signal = (string) substr($signal, $a + 1);
         }
         if ($signal == NULL) {
             // intentionally ==
             throw new InvalidLinkException('Signal must be non-empty string.');
         }
         $destination = 'this';
     }
     if ($destination == NULL) {
         // intentionally ==
         throw new InvalidLinkException('Destination must be non-empty string.');
     }
     // 5) presenter: action
     $current = FALSE;
     $a = strrpos($destination, ':');
     if ($a === FALSE) {
         $action = $destination === 'this' ? $this->action : $destination;
         $presenter = $this->getName();
         $presenterClass = get_class($this);
     } else {
         $action = (string) substr($destination, $a + 1);
         if ($destination[0] === ':') {
             // absolute
             if ($a < 2) {
                 throw new InvalidLinkException("Missing presenter name in '{$destination}'.");
             }
             $presenter = substr($destination, 1, $a - 1);
         } else {
             // relative
             $presenter = $this->getName();
             $b = strrpos($presenter, ':');
             if ($b === FALSE) {
                 // no module
                 $presenter = substr($destination, 0, $a);
             } else {
                 // with module
                 $presenter = substr($presenter, 0, $b + 1) . substr($destination, 0, $a);
             }
         }
         if (!$this->presenterFactory) {
             throw new Nette\InvalidStateException('Unable to create link to other presenter, service PresenterFactory has not been set.');
         }
         try {
             $presenterClass = $this->presenterFactory->getPresenterClass($presenter);
         } catch (Application\InvalidPresenterException $e) {
             throw new InvalidLinkException($e->getMessage(), NULL, $e);
         }
     }
     // PROCESS SIGNAL ARGUMENTS
     if (isset($signal)) {
         // $component must be IStatePersistent
         $reflection = new PresenterComponentReflection(get_class($component));
         if ($signal === 'this') {
             // means "no signal"
             $signal = '';
             if (array_key_exists(0, $args)) {
                 throw new InvalidLinkException("Unable to pass parameters to 'this!' signal.");
             }
         } elseif (strpos($signal, self::NAME_SEPARATOR) === FALSE) {
             // counterpart of signalReceived() & tryCall()
             $method = $component->formatSignalMethod($signal);
             if (!$reflection->hasCallableMethod($method)) {
                 throw new InvalidLinkException("Unknown signal '{$signal}', missing handler {$reflection->getName()}::{$method}()");
             }
             if ($args) {
                 // convert indexed parameters to named
                 self::argsToParams(get_class($component), $method, $args);
             }
         }
         // counterpart of IStatePersistent
         if ($args && array_intersect_key($args, $reflection->getPersistentParams())) {
             $component->saveState($args);
         }
         if ($args && $component !== $this) {
             $prefix = $component->getUniqueId() . self::NAME_SEPARATOR;
             foreach ($args as $key => $val) {
                 unset($args[$key]);
                 $args[$prefix . $key] = $val;
             }
         }
     }
     // PROCESS ARGUMENTS
     if (is_subclass_of($presenterClass, __CLASS__)) {
         if ($action === '') {
             $action = self::DEFAULT_ACTION;
         }
         $current = ($action === '*' || strcasecmp($action, $this->action) === 0) && $presenterClass === get_class($this);
         $reflection = new PresenterComponentReflection($presenterClass);
         if ($args || $destination === 'this') {
             // counterpart of run() & tryCall()
             $method = $presenterClass::formatActionMethod($action);
             if (!$reflection->hasCallableMethod($method)) {
                 $method = $presenterClass::formatRenderMethod($action);
                 if (!$reflection->hasCallableMethod($method)) {
                     $method = NULL;
                 }
             }
             // convert indexed parameters to named
             if ($method === NULL) {
                 if (array_key_exists(0, $args)) {
                     throw new InvalidLinkException("Unable to pass parameters to action '{$presenter}:{$action}', missing corresponding method.");
                 }
             } elseif ($destination === 'this') {
                 self::argsToParams($presenterClass, $method, $args, $this->params);
             } else {
                 self::argsToParams($presenterClass, $method, $args);
             }
         }
         // counterpart of IStatePersistent
         if ($args && array_intersect_key($args, $reflection->getPersistentParams())) {
             $this->saveState($args, $reflection);
         }
         if ($mode === 'redirect') {
             $this->saveGlobalState();
         }
         $globalState = $this->getGlobalState($destination === 'this' ? NULL : $presenterClass);
         if ($current && $args) {
             $tmp = $globalState + $this->params;
             foreach ($args as $key => $val) {
                 if (http_build_query([$val]) !== (isset($tmp[$key]) ? http_build_query([$tmp[$key]]) : '')) {
                     $current = FALSE;
                     break;
                 }
             }
         }
         $args += $globalState;
     }
     // ADD ACTION & SIGNAL & FLASH
     if ($action) {
         $args[self::ACTION_KEY] = $action;
     }
     if (!empty($signal)) {
         $args[self::SIGNAL_KEY] = $component->getParameterId($signal);
         $current = $current && $args[self::SIGNAL_KEY] === $this->getParameter(self::SIGNAL_KEY);
     }
     if (($mode === 'redirect' || $mode === 'forward') && $this->hasFlashSession()) {
         $args[self::FLASH_KEY] = $this->getParameter(self::FLASH_KEY);
     }
     $this->lastCreatedRequest = new Application\Request($presenter, Application\Request::FORWARD, $args, [], []);
     $this->lastCreatedRequestFlag = ['current' => $current];
     if ($mode === 'forward' || $mode === 'test') {
         return;
     }
     // CONSTRUCT URL
     static $refUrl;
     if ($refUrl === NULL) {
         $refUrl = new Http\Url($this->httpRequest->getUrl());
         $refUrl->setPath($this->httpRequest->getUrl()->getScriptPath());
     }
     if (!$this->router) {
         throw new Nette\InvalidStateException('Unable to generate URL, service Router has not been set.');
     }
     $url = $this->router->constructUrl($this->lastCreatedRequest, $refUrl);
     if ($url === NULL) {
         unset($args[self::ACTION_KEY]);
         $params = urldecode(http_build_query($args, NULL, ', '));
         throw new InvalidLinkException("No route for {$presenter}:{$action}({$params})");
     }
     // make URL relative if possible
     if ($mode === 'link' && $scheme === FALSE && !$this->absoluteUrls) {
         $hostUrl = $refUrl->getHostUrl() . '/';
         if (strncmp($url, $hostUrl, strlen($hostUrl)) === 0) {
             $url = substr($url, strlen($hostUrl) - 1);
         }
     }
     return $url . $fragment;
 }
예제 #12
0
 public function buildHttpRequest(AppRequest $appRequest, IRouter $router)
 {
     return new HttpRequest(new UrlScript($router->constructUrl($appRequest, new Url('http://instante.test/'))), NULL, $this->post, $this->filesBuilder->getFileUploads(), $this->cookies, $this->headers, $this->method, $this->remoteAddress, $this->remoteHost, $this->rawBodyCallback);
 }