public function testGetParameters() { $requestContext = new RequestContext(); $this->assertEquals(array(), $requestContext->getParameters()); $requestContext->setParameters(array('foo' => 'bar')); $this->assertEquals(array('foo' => 'bar'), $requestContext->getParameters()); }
/** * Rebuild the request object from a URL with the help of the RequestContext. * * If the request context is not set, this simply returns the request object built from $uri. * * @param string $uri * * @return Request */ private function rebuildRequest($uri) { if (!$this->context) { return Request::create($uri); } $server = array(); if ($this->context->getHost()) { $server['SERVER_NAME'] = $this->context->getHost(); $server['HTTP_HOST'] = $this->context->getHost(); } if ($this->context->getBaseUrl()) { $uri = $this->context->getBaseUrl() . $uri; $server['SCRIPT_FILENAME'] = $this->context->getBaseUrl(); $server['PHP_SELF'] = $this->context->getBaseUrl(); } if ('https' === $this->context->getScheme()) { $server['HTTPS'] = 'on'; $server['SERVER_PORT'] = $this->context->getHttpsPort(); if (443 !== $this->context->getHttpsPort()) { // this is parsed from the host by symfony request // https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/Request.php#L971 $server['HTTP_HOST'] .= ':' . $this->context->getHttpsPort(); } } else { $server['SERVER_PORT'] = $this->context->getHttpPort(); if (80 !== $this->context->getHttpPort()) { // this is parsed from the host by symfony request // https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/Request.php#L971 $server['HTTP_HOST'] .= ':' . $this->context->getHttpPort(); } } return Request::create($uri, $this->context->getMethod(), $this->context->getParameters(), array(), array(), $server); }
public function generate($name, array $parameters = array(), $referenceType = self::ABSOLUTE_PATH, $scheme = null) { $contextParameters = array_deep_merge($this->sessionDefaultParameters, $this->defaultParameters, $this->context->getParameters()); $oldContextParameters = $this->context->getParameters(); $this->context->setParameters($contextParameters); $oldScheme = null; if ($scheme) { $oldScheme = $this->context->getScheme(); $this->context->setScheme($scheme); } $oldHost = $this->context->getHost(); $context = $this->context; $finalize = new OutOfScopeFinalize(function () use($oldContextParameters, $oldScheme, $oldHost, $context, $scheme) { if ($scheme) { $context->setScheme($oldScheme); } $context->setHost($oldHost); $context->setParameters($oldContextParameters); }); $cultures = $this->getCultures(array_merge($contextParameters, $parameters)); $route = null; foreach ($cultures as $culture) { $routeName = $this->getI18nRouteName($name, $culture); if ($this->routeCollection->get($routeName)) { try { $host = $this->getHostForCulture($culture == '' ? 'default' : $culture); $this->context->setHost($host); if ($host != $oldHost) { $referenceType = self::ABSOLUTE_URL; } } catch (NoHostFoundForCultureException $e) { //We do nothing with the exception, it will use the request domain } $route = $this->urlGenerator->generate($routeName, $parameters, $referenceType); break; } } if (is_null($route)) { $route = $this->urlGenerator->generate($name, $parameters); } return $route; }
/** * Rebuild the request object from a URL with the help of the RequestContext. * * If the request context is not set, this simply returns the request object built from $uri. * * @param string $pathinfo * * @return Request */ private function rebuildRequest($pathinfo) { if (!$this->context) { return Request::create('http://localhost' . $pathinfo); } $uri = $pathinfo; $server = array(); if ($this->context->getBaseUrl()) { $uri = $this->context->getBaseUrl() . $pathinfo; $server['SCRIPT_FILENAME'] = $this->context->getBaseUrl(); $server['PHP_SELF'] = $this->context->getBaseUrl(); } $host = $this->context->getHost() ?: 'localhost'; if ('https' === $this->context->getScheme() && 443 !== $this->context->getHttpsPort()) { $host .= ':' . $this->context->getHttpsPort(); } if ('http' === $this->context->getScheme() && 80 !== $this->context->getHttpPort()) { $host .= ':' . $this->context->getHttpPort(); } $uri = $this->context->getScheme() . '://' . $host . $uri . '?' . $this->context->getQueryString(); return Request::create($uri, $this->context->getMethod(), $this->context->getParameters(), array(), array(), $server); }
/** * @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route * @throws InvalidParameterException When a parameter value for a placeholder is not correct because * it does not match the requirement */ protected function doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens, array $requiredSchemes = array()) { $variables = array_flip($variables); $mergedParams = array_replace($defaults, $this->context->getParameters(), $parameters); // all params must be given if ($diff = array_diff_key($variables, $mergedParams)) { throw new MissingMandatoryParametersException(sprintf('Some mandatory parameters are missing ("%s") to generate a URL for route "%s".', implode('", "', array_keys($diff)), $name)); } $url = ''; $optional = true; foreach ($tokens as $token) { if ('variable' === $token[0]) { if (!$optional || !array_key_exists($token[3], $defaults) || null !== $mergedParams[$token[3]] && (string) $mergedParams[$token[3]] !== (string) $defaults[$token[3]]) { // check requirement if (null !== $this->strictRequirements && !preg_match('#^' . $token[2] . '$#', $mergedParams[$token[3]])) { $message = sprintf('Parameter "%s" for route "%s" must match "%s" ("%s" given) to generate a corresponding URL.', $token[3], $name, $token[2], $mergedParams[$token[3]]); if ($this->strictRequirements) { throw new InvalidParameterException($message); } if ($this->logger) { $this->logger->error($message); } return; } $url = $token[1] . $mergedParams[$token[3]] . $url; $optional = false; } } else { // static text $url = $token[1] . $url; $optional = false; } } if ('' === $url) { $url = '/'; } // the contexts base URL is already encoded (see Symfony\Component\HttpFoundation\Request) $url = strtr(rawurlencode($url), $this->decodedChars); // the path segments "." and ".." are interpreted as relative reference when resolving a URI; see http://tools.ietf.org/html/rfc3986#section-3.3 // so we need to encode them as they are not used for this purpose here // otherwise we would generate a URI that, when followed by a user agent (e.g. browser), does not match this route $url = strtr($url, array('/../' => '/%2E%2E/', '/./' => '/%2E/')); if ('/..' === substr($url, -3)) { $url = substr($url, 0, -2) . '%2E%2E'; } elseif ('/.' === substr($url, -2)) { $url = substr($url, 0, -1) . '%2E'; } $schemeAuthority = ''; if ($host = $this->context->getHost()) { $scheme = $this->context->getScheme(); if ($requiredSchemes) { $schemeMatched = false; foreach ($requiredSchemes as $requiredScheme) { if ($scheme === $requiredScheme) { $schemeMatched = true; break; } } if (!$schemeMatched) { $referenceType = self::ABSOLUTE_URL; $scheme = current($requiredSchemes); } } elseif (isset($requirements['_scheme']) && ($req = strtolower($requirements['_scheme'])) && $scheme !== $req) { // We do this for BC; to be removed if _scheme is not supported anymore $referenceType = self::ABSOLUTE_URL; $scheme = $req; } if ($hostTokens) { $routeHost = ''; foreach ($hostTokens as $token) { if ('variable' === $token[0]) { if (null !== $this->strictRequirements && !preg_match('#^' . $token[2] . '$#i', $mergedParams[$token[3]])) { $message = sprintf('Parameter "%s" for route "%s" must match "%s" ("%s" given) to generate a corresponding URL.', $token[3], $name, $token[2], $mergedParams[$token[3]]); if ($this->strictRequirements) { throw new InvalidParameterException($message); } if ($this->logger) { $this->logger->error($message); } return; } $routeHost = $token[1] . $mergedParams[$token[3]] . $routeHost; } else { $routeHost = $token[1] . $routeHost; } } if ($routeHost !== $host) { $host = $routeHost; if (self::ABSOLUTE_URL !== $referenceType) { $referenceType = self::NETWORK_PATH; } } } if (self::ABSOLUTE_URL === $referenceType || self::NETWORK_PATH === $referenceType) { $port = ''; if ('http' === $scheme && 80 != $this->context->getHttpPort()) { $port = ':' . $this->context->getHttpPort(); } elseif ('https' === $scheme && 443 != $this->context->getHttpsPort()) { $port = ':' . $this->context->getHttpsPort(); } $schemeAuthority = self::NETWORK_PATH === $referenceType ? '//' : "{$scheme}://"; $schemeAuthority .= $host . $port; } } if (self::RELATIVE_PATH === $referenceType) { $url = self::getRelativePath($this->context->getPathInfo(), $url); } else { $url = $schemeAuthority . $this->context->getBaseUrl() . $url; } // add a query string if needed $extra = array_diff_key($parameters, $variables, $defaults); if ($extra && ($query = http_build_query($extra, '', '&'))) { // "/" and "?" can be left decoded for better user experience, see // http://tools.ietf.org/html/rfc3986#section-3.4 $url .= '?' . strtr($query, array('%2F' => '/')); } return $url; }
/** * @throws MissingMandatoryParametersException When route has some missing mandatory parameters * @throws InvalidParameterException When a parameter value is not correct */ protected function doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $absolute, $hostnameTokens) { $variables = array_flip($variables); $mergedParams = array_replace($defaults, $this->context->getParameters(), $parameters); // all params must be given if ($diff = array_diff_key($variables, $mergedParams)) { throw new MissingMandatoryParametersException(sprintf('The "%s" route has some missing mandatory parameters ("%s").', $name, implode('", "', array_keys($diff)))); } $url = ''; $optional = true; foreach ($tokens as $token) { if ('variable' === $token[0]) { if (!$optional || !array_key_exists($token[3], $defaults) || (string) $mergedParams[$token[3]] !== (string) $defaults[$token[3]]) { // check requirement if (null !== $this->strictRequirements && !preg_match('#^' . $token[2] . '$#', $mergedParams[$token[3]])) { $message = sprintf('Parameter "%s" for route "%s" must match "%s" ("%s" given).', $token[3], $name, $token[2], $mergedParams[$token[3]]); if ($this->strictRequirements) { throw new InvalidParameterException($message); } if ($this->logger) { $this->logger->err($message); } return null; } $url = $token[1] . $mergedParams[$token[3]] . $url; $optional = false; } } else { // static text $url = $token[1] . $url; $optional = false; } } if ('' === $url) { $url = '/'; } // do not encode the contexts base url as it is already encoded (see Symfony\Component\HttpFoundation\Request) $url = $this->context->getBaseUrl() . strtr(rawurlencode($url), $this->decodedChars); // the path segments "." and ".." are interpreted as relative reference when resolving a URI; see http://tools.ietf.org/html/rfc3986#section-3.3 // so we need to encode them as they are not used for this purpose here // otherwise we would generate a URI that, when followed by a user agent (e.g. browser), does not match this route $url = strtr($url, array('/../' => '/%2E%2E/', '/./' => '/%2E/')); if ('/..' === substr($url, -3)) { $url = substr($url, 0, -2) . '%2E%2E'; } elseif ('/.' === substr($url, -2)) { $url = substr($url, 0, -1) . '%2E'; } // add a query string if needed $extra = array_diff_key($parameters, $variables); if ($extra && ($query = http_build_query($extra, '', '&'))) { $url .= '?' . $query; } if ($host = $this->context->getHost()) { $scheme = $this->context->getScheme(); if (isset($requirements['_scheme']) && ($req = strtolower($requirements['_scheme'])) && $scheme != $req) { $absolute = true; $scheme = $req; } if ($hostnameTokens) { $routeHost = ''; foreach ($hostnameTokens as $token) { if ('variable' === $token[0]) { if (null !== $this->strictRequirements && !preg_match('#^' . $token[2] . '$#', $mergedParams[$token[3]])) { $message = sprintf('Parameter "%s" for route "%s" must match "%s" ("%s" given).', $token[3], $name, $token[2], $mergedParams[$token[3]]); if ($this->strictRequirements) { throw new InvalidParameterException($message); } if ($this->logger) { $this->logger->err($message); } return null; } $routeHost = $token[1] . $mergedParams[$token[3]] . $routeHost; } elseif ('text' === $token[0]) { $routeHost = $token[1] . $routeHost; } } if ($routeHost != $host) { $host = $routeHost; $absolute = true; } } if ($absolute) { $port = ''; if ('http' === $scheme && 80 != $this->context->getHttpPort()) { $port = ':' . $this->context->getHttpPort(); } elseif ('https' === $scheme && 443 != $this->context->getHttpsPort()) { $port = ':' . $this->context->getHttpsPort(); } $url = $scheme . '://' . $host . $port . $url; } } return $url; }