comparison vendor/symfony/routing/Generator/UrlGenerator.php @ 17:129ea1e6d783

Update, including to Drupal core 8.6.10
author Chris Cannam
date Thu, 28 Feb 2019 13:21:36 +0000
parents 1fec387a4317
children af1871eacc83
comparison
equal deleted inserted replaced
16:c2387f117808 17:129ea1e6d783
9 * file that was distributed with this source code. 9 * file that was distributed with this source code.
10 */ 10 */
11 11
12 namespace Symfony\Component\Routing\Generator; 12 namespace Symfony\Component\Routing\Generator;
13 13
14 use Psr\Log\LoggerInterface;
15 use Symfony\Component\Routing\Exception\InvalidParameterException;
16 use Symfony\Component\Routing\Exception\MissingMandatoryParametersException;
17 use Symfony\Component\Routing\Exception\RouteNotFoundException;
18 use Symfony\Component\Routing\RequestContext;
14 use Symfony\Component\Routing\RouteCollection; 19 use Symfony\Component\Routing\RouteCollection;
15 use Symfony\Component\Routing\RequestContext;
16 use Symfony\Component\Routing\Exception\InvalidParameterException;
17 use Symfony\Component\Routing\Exception\RouteNotFoundException;
18 use Symfony\Component\Routing\Exception\MissingMandatoryParametersException;
19 use Psr\Log\LoggerInterface;
20 20
21 /** 21 /**
22 * UrlGenerator can generate a URL or a path for any route in the RouteCollection 22 * UrlGenerator can generate a URL or a path for any route in the RouteCollection
23 * based on the passed parameters. 23 * based on the passed parameters.
24 * 24 *
43 * PHP's rawurlencode() encodes all chars except "a-zA-Z0-9-._~" according to RFC 3986. But we want to allow some chars 43 * PHP's rawurlencode() encodes all chars except "a-zA-Z0-9-._~" according to RFC 3986. But we want to allow some chars
44 * to be used in their literal form (reasons below). Other chars inside the path must of course be encoded, e.g. 44 * to be used in their literal form (reasons below). Other chars inside the path must of course be encoded, e.g.
45 * "?" and "#" (would be interpreted wrongly as query and fragment identifier), 45 * "?" and "#" (would be interpreted wrongly as query and fragment identifier),
46 * "'" and """ (are used as delimiters in HTML). 46 * "'" and """ (are used as delimiters in HTML).
47 */ 47 */
48 protected $decodedChars = array( 48 protected $decodedChars = [
49 // the slash can be used to designate a hierarchical structure and we want allow using it with this meaning 49 // the slash can be used to designate a hierarchical structure and we want allow using it with this meaning
50 // some webservers don't allow the slash in encoded form in the path for security reasons anyway 50 // some webservers don't allow the slash in encoded form in the path for security reasons anyway
51 // see http://stackoverflow.com/questions/4069002/http-400-if-2f-part-of-get-url-in-jboss 51 // see http://stackoverflow.com/questions/4069002/http-400-if-2f-part-of-get-url-in-jboss
52 '%2F' => '/', 52 '%2F' => '/',
53 // the following chars are general delimiters in the URI specification but have only special meaning in the authority component 53 // the following chars are general delimiters in the URI specification but have only special meaning in the authority component
61 '%3D' => '=', 61 '%3D' => '=',
62 '%2B' => '+', 62 '%2B' => '+',
63 '%21' => '!', 63 '%21' => '!',
64 '%2A' => '*', 64 '%2A' => '*',
65 '%7C' => '|', 65 '%7C' => '|',
66 ); 66 ];
67 67
68 public function __construct(RouteCollection $routes, RequestContext $context, LoggerInterface $logger = null) 68 public function __construct(RouteCollection $routes, RequestContext $context, LoggerInterface $logger = null)
69 { 69 {
70 $this->routes = $routes; 70 $this->routes = $routes;
71 $this->context = $context; 71 $this->context = $context;
105 } 105 }
106 106
107 /** 107 /**
108 * {@inheritdoc} 108 * {@inheritdoc}
109 */ 109 */
110 public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH) 110 public function generate($name, $parameters = [], $referenceType = self::ABSOLUTE_PATH)
111 { 111 {
112 if (null === $route = $this->routes->get($name)) { 112 if (null === $route = $this->routes->get($name)) {
113 throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name)); 113 throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name));
114 } 114 }
115 115
122 /** 122 /**
123 * @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route 123 * @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route
124 * @throws InvalidParameterException When a parameter value for a placeholder is not correct because 124 * @throws InvalidParameterException When a parameter value for a placeholder is not correct because
125 * it does not match the requirement 125 * it does not match the requirement
126 */ 126 */
127 protected function doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens, array $requiredSchemes = array()) 127 protected function doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens, array $requiredSchemes = [])
128 { 128 {
129 $variables = array_flip($variables); 129 $variables = array_flip($variables);
130 $mergedParams = array_replace($defaults, $this->context->getParameters(), $parameters); 130 $mergedParams = array_replace($defaults, $this->context->getParameters(), $parameters);
131 131
132 // all params must be given 132 // all params must be given
141 if ('variable' === $token[0]) { 141 if ('variable' === $token[0]) {
142 if (!$optional || !array_key_exists($token[3], $defaults) || null !== $mergedParams[$token[3]] && (string) $mergedParams[$token[3]] !== (string) $defaults[$token[3]]) { 142 if (!$optional || !array_key_exists($token[3], $defaults) || null !== $mergedParams[$token[3]] && (string) $mergedParams[$token[3]] !== (string) $defaults[$token[3]]) {
143 // check requirement 143 // check requirement
144 if (null !== $this->strictRequirements && !preg_match('#^'.$token[2].'$#'.(empty($token[4]) ? '' : 'u'), $mergedParams[$token[3]])) { 144 if (null !== $this->strictRequirements && !preg_match('#^'.$token[2].'$#'.(empty($token[4]) ? '' : 'u'), $mergedParams[$token[3]])) {
145 if ($this->strictRequirements) { 145 if ($this->strictRequirements) {
146 throw new InvalidParameterException(strtr($message, array('{parameter}' => $token[3], '{route}' => $name, '{expected}' => $token[2], '{given}' => $mergedParams[$token[3]]))); 146 throw new InvalidParameterException(strtr($message, ['{parameter}' => $token[3], '{route}' => $name, '{expected}' => $token[2], '{given}' => $mergedParams[$token[3]]]));
147 } 147 }
148 148
149 if ($this->logger) { 149 if ($this->logger) {
150 $this->logger->error($message, array('parameter' => $token[3], 'route' => $name, 'expected' => $token[2], 'given' => $mergedParams[$token[3]])); 150 $this->logger->error($message, ['parameter' => $token[3], 'route' => $name, 'expected' => $token[2], 'given' => $mergedParams[$token[3]]]);
151 } 151 }
152 152
153 return; 153 return;
154 } 154 }
155 155
171 $url = strtr(rawurlencode($url), $this->decodedChars); 171 $url = strtr(rawurlencode($url), $this->decodedChars);
172 172
173 // the path segments "." and ".." are interpreted as relative reference when resolving a URI; see http://tools.ietf.org/html/rfc3986#section-3.3 173 // the path segments "." and ".." are interpreted as relative reference when resolving a URI; see http://tools.ietf.org/html/rfc3986#section-3.3
174 // so we need to encode them as they are not used for this purpose here 174 // so we need to encode them as they are not used for this purpose here
175 // otherwise we would generate a URI that, when followed by a user agent (e.g. browser), does not match this route 175 // otherwise we would generate a URI that, when followed by a user agent (e.g. browser), does not match this route
176 $url = strtr($url, array('/../' => '/%2E%2E/', '/./' => '/%2E/')); 176 $url = strtr($url, ['/../' => '/%2E%2E/', '/./' => '/%2E/']);
177 if ('/..' === substr($url, -3)) { 177 if ('/..' === substr($url, -3)) {
178 $url = substr($url, 0, -2).'%2E%2E'; 178 $url = substr($url, 0, -2).'%2E%2E';
179 } elseif ('/.' === substr($url, -2)) { 179 } elseif ('/.' === substr($url, -2)) {
180 $url = substr($url, 0, -1).'%2E'; 180 $url = substr($url, 0, -1).'%2E';
181 } 181 }
183 $schemeAuthority = ''; 183 $schemeAuthority = '';
184 $host = $this->context->getHost(); 184 $host = $this->context->getHost();
185 $scheme = $this->context->getScheme(); 185 $scheme = $this->context->getScheme();
186 186
187 if ($requiredSchemes) { 187 if ($requiredSchemes) {
188 if (!in_array($scheme, $requiredSchemes, true)) { 188 if (!\in_array($scheme, $requiredSchemes, true)) {
189 $referenceType = self::ABSOLUTE_URL; 189 $referenceType = self::ABSOLUTE_URL;
190 $scheme = current($requiredSchemes); 190 $scheme = current($requiredSchemes);
191 } 191 }
192 } 192 }
193 193
195 $routeHost = ''; 195 $routeHost = '';
196 foreach ($hostTokens as $token) { 196 foreach ($hostTokens as $token) {
197 if ('variable' === $token[0]) { 197 if ('variable' === $token[0]) {
198 if (null !== $this->strictRequirements && !preg_match('#^'.$token[2].'$#i'.(empty($token[4]) ? '' : 'u'), $mergedParams[$token[3]])) { 198 if (null !== $this->strictRequirements && !preg_match('#^'.$token[2].'$#i'.(empty($token[4]) ? '' : 'u'), $mergedParams[$token[3]])) {
199 if ($this->strictRequirements) { 199 if ($this->strictRequirements) {
200 throw new InvalidParameterException(strtr($message, array('{parameter}' => $token[3], '{route}' => $name, '{expected}' => $token[2], '{given}' => $mergedParams[$token[3]]))); 200 throw new InvalidParameterException(strtr($message, ['{parameter}' => $token[3], '{route}' => $name, '{expected}' => $token[2], '{given}' => $mergedParams[$token[3]]]));
201 } 201 }
202 202
203 if ($this->logger) { 203 if ($this->logger) {
204 $this->logger->error($message, array('parameter' => $token[3], 'route' => $name, 'expected' => $token[2], 'given' => $mergedParams[$token[3]])); 204 $this->logger->error($message, ['parameter' => $token[3], 'route' => $name, 'expected' => $token[2], 'given' => $mergedParams[$token[3]]]);
205 } 205 }
206 206
207 return; 207 return;
208 } 208 }
209 209
256 } 256 }
257 257
258 if ($extra && $query = http_build_query($extra, '', '&', PHP_QUERY_RFC3986)) { 258 if ($extra && $query = http_build_query($extra, '', '&', PHP_QUERY_RFC3986)) {
259 // "/" and "?" can be left decoded for better user experience, see 259 // "/" and "?" can be left decoded for better user experience, see
260 // http://tools.ietf.org/html/rfc3986#section-3.4 260 // http://tools.ietf.org/html/rfc3986#section-3.4
261 $url .= '?'.strtr($query, array('%2F' => '/')); 261 $url .= '?'.strtr($query, ['%2F' => '/']);
262 } 262 }
263 263
264 if ('' !== $fragment) { 264 if ('' !== $fragment) {
265 $url .= '#'.strtr(rawurlencode($fragment), array('%2F' => '/', '%3F' => '?')); 265 $url .= '#'.strtr(rawurlencode($fragment), ['%2F' => '/', '%3F' => '?']);
266 } 266 }
267 267
268 return $url; 268 return $url;
269 } 269 }
270 270
306 break; 306 break;
307 } 307 }
308 } 308 }
309 309
310 $targetDirs[] = $targetFile; 310 $targetDirs[] = $targetFile;
311 $path = str_repeat('../', count($sourceDirs)).implode('/', $targetDirs); 311 $path = str_repeat('../', \count($sourceDirs)).implode('/', $targetDirs);
312 312
313 // A reference to the same base directory or an empty subdirectory must be prefixed with "./". 313 // A reference to the same base directory or an empty subdirectory must be prefixed with "./".
314 // This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used 314 // This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used
315 // as the first segment of a relative-path reference, as it would be mistaken for a scheme name 315 // as the first segment of a relative-path reference, as it would be mistaken for a scheme name
316 // (see http://tools.ietf.org/html/rfc3986#section-4.2). 316 // (see http://tools.ietf.org/html/rfc3986#section-4.2).