[ Index ] |
PHP Cross Reference of phpBB-3.3.14-deutsch |
[Summary view] [Print] [Text view]
1 <?php 2 3 /* 4 * This file is part of the Symfony package. 5 * 6 * (c) Fabien Potencier <fabien@symfony.com> 7 * 8 * For the full copyright and license information, please view the LICENSE 9 * file that was distributed with this source code. 10 */ 11 12 namespace Symfony\Component\Routing\Matcher; 13 14 use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; 15 use Symfony\Component\ExpressionLanguage\ExpressionLanguage; 16 use Symfony\Component\HttpFoundation\Request; 17 use Symfony\Component\Routing\Exception\MethodNotAllowedException; 18 use Symfony\Component\Routing\Exception\NoConfigurationException; 19 use Symfony\Component\Routing\Exception\ResourceNotFoundException; 20 use Symfony\Component\Routing\RequestContext; 21 use Symfony\Component\Routing\Route; 22 use Symfony\Component\Routing\RouteCollection; 23 24 /** 25 * UrlMatcher matches URL based on a set of routes. 26 * 27 * @author Fabien Potencier <fabien@symfony.com> 28 */ 29 class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface 30 { 31 const REQUIREMENT_MATCH = 0; 32 const REQUIREMENT_MISMATCH = 1; 33 const ROUTE_MATCH = 2; 34 35 protected $context; 36 protected $allow = []; 37 protected $routes; 38 protected $request; 39 protected $expressionLanguage; 40 41 /** 42 * @var ExpressionFunctionProviderInterface[] 43 */ 44 protected $expressionLanguageProviders = []; 45 46 public function __construct(RouteCollection $routes, RequestContext $context) 47 { 48 $this->routes = $routes; 49 $this->context = $context; 50 } 51 52 /** 53 * {@inheritdoc} 54 */ 55 public function setContext(RequestContext $context) 56 { 57 $this->context = $context; 58 } 59 60 /** 61 * {@inheritdoc} 62 */ 63 public function getContext() 64 { 65 return $this->context; 66 } 67 68 /** 69 * {@inheritdoc} 70 */ 71 public function match($pathinfo) 72 { 73 $this->allow = []; 74 75 if ($ret = $this->matchCollection(rawurldecode($pathinfo), $this->routes)) { 76 return $ret; 77 } 78 79 if ('/' === $pathinfo && !$this->allow) { 80 throw new NoConfigurationException(); 81 } 82 83 throw 0 < \count($this->allow) ? new MethodNotAllowedException(array_unique($this->allow)) : new ResourceNotFoundException(sprintf('No routes found for "%s".', $pathinfo)); 84 } 85 86 /** 87 * {@inheritdoc} 88 */ 89 public function matchRequest(Request $request) 90 { 91 $this->request = $request; 92 93 $ret = $this->match($request->getPathInfo()); 94 95 $this->request = null; 96 97 return $ret; 98 } 99 100 public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider) 101 { 102 $this->expressionLanguageProviders[] = $provider; 103 } 104 105 /** 106 * Tries to match a URL with a set of routes. 107 * 108 * @param string $pathinfo The path info to be parsed 109 * @param RouteCollection $routes The set of routes 110 * 111 * @return array An array of parameters 112 * 113 * @throws NoConfigurationException If no routing configuration could be found 114 * @throws ResourceNotFoundException If the resource could not be found 115 * @throws MethodNotAllowedException If the resource was found but the request method is not allowed 116 */ 117 protected function matchCollection($pathinfo, RouteCollection $routes) 118 { 119 // HEAD and GET are equivalent as per RFC 120 if ('HEAD' === $method = $this->context->getMethod()) { 121 $method = 'GET'; 122 } 123 $supportsTrailingSlash = '/' !== $pathinfo && '' !== $pathinfo && $this instanceof RedirectableUrlMatcherInterface; 124 125 foreach ($routes as $name => $route) { 126 $compiledRoute = $route->compile(); 127 $staticPrefix = $compiledRoute->getStaticPrefix(); 128 $requiredMethods = $route->getMethods(); 129 130 // check the static prefix of the URL first. Only use the more expensive preg_match when it matches 131 if ('' === $staticPrefix || 0 === strpos($pathinfo, $staticPrefix)) { 132 // no-op 133 } elseif (!$supportsTrailingSlash || ($requiredMethods && !\in_array('GET', $requiredMethods)) || 'GET' !== $method) { 134 continue; 135 } elseif ('/' === substr($staticPrefix, -1) && substr($staticPrefix, 0, -1) === $pathinfo) { 136 return $this->allow = []; 137 } else { 138 continue; 139 } 140 $regex = $compiledRoute->getRegex(); 141 142 if ($supportsTrailingSlash && $pos = strpos($regex, '/$')) { 143 $regex = substr($regex, 0, $pos).'/?$'.substr($regex, $pos + 2); 144 $hasTrailingSlash = true; 145 } else { 146 $hasTrailingSlash = false; 147 } 148 149 if (!preg_match($regex, $pathinfo, $matches)) { 150 continue; 151 } 152 153 if ($hasTrailingSlash && '/' !== substr($pathinfo, -1)) { 154 if ((!$requiredMethods || \in_array('GET', $requiredMethods)) && 'GET' === $method) { 155 return $this->allow = []; 156 } 157 continue; 158 } 159 160 $hostMatches = []; 161 if ($compiledRoute->getHostRegex() && !preg_match($compiledRoute->getHostRegex(), $this->context->getHost(), $hostMatches)) { 162 continue; 163 } 164 165 $status = $this->handleRouteRequirements($pathinfo, $name, $route); 166 167 if (self::REQUIREMENT_MISMATCH === $status[0]) { 168 continue; 169 } 170 171 // check HTTP method requirement 172 if ($requiredMethods) { 173 if (!\in_array($method, $requiredMethods)) { 174 if (self::REQUIREMENT_MATCH === $status[0]) { 175 $this->allow = array_merge($this->allow, $requiredMethods); 176 } 177 178 continue; 179 } 180 } 181 182 return $this->getAttributes($route, $name, array_replace($matches, $hostMatches, isset($status[1]) ? $status[1] : [])); 183 } 184 185 return []; 186 } 187 188 /** 189 * Returns an array of values to use as request attributes. 190 * 191 * As this method requires the Route object, it is not available 192 * in matchers that do not have access to the matched Route instance 193 * (like the PHP and Apache matcher dumpers). 194 * 195 * @param Route $route The route we are matching against 196 * @param string $name The name of the route 197 * @param array $attributes An array of attributes from the matcher 198 * 199 * @return array An array of parameters 200 */ 201 protected function getAttributes(Route $route, $name, array $attributes) 202 { 203 $attributes['_route'] = $name; 204 205 return $this->mergeDefaults($attributes, $route->getDefaults()); 206 } 207 208 /** 209 * Handles specific route requirements. 210 * 211 * @param string $pathinfo The path 212 * @param string $name The route name 213 * @param Route $route The route 214 * 215 * @return array The first element represents the status, the second contains additional information 216 */ 217 protected function handleRouteRequirements($pathinfo, $name, Route $route) 218 { 219 // expression condition 220 if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), ['context' => $this->context, 'request' => $this->request ?: $this->createRequest($pathinfo)])) { 221 return [self::REQUIREMENT_MISMATCH, null]; 222 } 223 224 // check HTTP scheme requirement 225 $scheme = $this->context->getScheme(); 226 $status = $route->getSchemes() && !$route->hasScheme($scheme) ? self::REQUIREMENT_MISMATCH : self::REQUIREMENT_MATCH; 227 228 return [$status, null]; 229 } 230 231 /** 232 * Get merged default parameters. 233 * 234 * @param array $params The parameters 235 * @param array $defaults The defaults 236 * 237 * @return array Merged default parameters 238 */ 239 protected function mergeDefaults($params, $defaults) 240 { 241 foreach ($params as $key => $value) { 242 if (!\is_int($key)) { 243 $defaults[$key] = $value; 244 } 245 } 246 247 return $defaults; 248 } 249 250 protected function getExpressionLanguage() 251 { 252 if (null === $this->expressionLanguage) { 253 if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { 254 throw new \RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); 255 } 256 $this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders); 257 } 258 259 return $this->expressionLanguage; 260 } 261 262 /** 263 * @internal 264 */ 265 protected function createRequest($pathinfo) 266 { 267 if (!class_exists('Symfony\Component\HttpFoundation\Request')) { 268 return null; 269 } 270 271 return Request::create($this->context->getScheme().'://'.$this->context->getHost().$this->context->getBaseUrl().$pathinfo, $this->context->getMethod(), $this->context->getParameters(), [], [], [ 272 'SCRIPT_FILENAME' => $this->context->getBaseUrl(), 273 'SCRIPT_NAME' => $this->context->getBaseUrl(), 274 ]); 275 } 276 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Mon Nov 25 19:05:08 2024 | Cross-referenced by PHPXref 0.7.1 |