Verzeichnisstruktur phpBB-3.3.15


Veröffentlicht
28.08.2024

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

UrlMatcher.php

Zuletzt modifiziert: 02.04.2025, 15:03 - Dateigröße: 8.97 KiB


001  <?php
002   
003  /*
004   * This file is part of the Symfony package.
005   *
006   * (c) Fabien Potencier <fabien@symfony.com>
007   *
008   * For the full copyright and license information, please view the LICENSE
009   * file that was distributed with this source code.
010   */
011   
012  namespace Symfony\Component\Routing\Matcher;
013   
014  use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
015  use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
016  use Symfony\Component\HttpFoundation\Request;
017  use Symfony\Component\Routing\Exception\MethodNotAllowedException;
018  use Symfony\Component\Routing\Exception\NoConfigurationException;
019  use Symfony\Component\Routing\Exception\ResourceNotFoundException;
020  use Symfony\Component\Routing\RequestContext;
021  use Symfony\Component\Routing\Route;
022  use Symfony\Component\Routing\RouteCollection;
023   
024  /**
025   * UrlMatcher matches URL based on a set of routes.
026   *
027   * @author Fabien Potencier <fabien@symfony.com>
028   */
029  class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface
030  {
031      const REQUIREMENT_MATCH = 0;
032      const REQUIREMENT_MISMATCH = 1;
033      const ROUTE_MATCH = 2;
034   
035      protected $context;
036      protected $allow = [];
037      protected $routes;
038      protected $request;
039      protected $expressionLanguage;
040   
041      /**
042       * @var ExpressionFunctionProviderInterface[]
043       */
044      protected $expressionLanguageProviders = [];
045   
046      public function __construct(RouteCollection $routes, RequestContext $context)
047      {
048          $this->routes = $routes;
049          $this->context = $context;
050      }
051   
052      /**
053       * {@inheritdoc}
054       */
055      public function setContext(RequestContext $context)
056      {
057          $this->context = $context;
058      }
059   
060      /**
061       * {@inheritdoc}
062       */
063      public function getContext()
064      {
065          return $this->context;
066      }
067   
068      /**
069       * {@inheritdoc}
070       */
071      public function match($pathinfo)
072      {
073          $this->allow = [];
074   
075          if ($ret = $this->matchCollection(rawurldecode($pathinfo), $this->routes)) {
076              return $ret;
077          }
078   
079          if ('/' === $pathinfo && !$this->allow) {
080              throw new NoConfigurationException();
081          }
082   
083          throw 0 < \count($this->allow) ? new MethodNotAllowedException(array_unique($this->allow)) : new ResourceNotFoundException(sprintf('No routes found for "%s".', $pathinfo));
084      }
085   
086      /**
087       * {@inheritdoc}
088       */
089      public function matchRequest(Request $request)
090      {
091          $this->request = $request;
092   
093          $ret = $this->match($request->getPathInfo());
094   
095          $this->request = null;
096   
097          return $ret;
098      }
099   
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  }
277