Verzeichnisstruktur phpBB-3.2.0


Veröffentlicht
06.01.2017

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

UrlGenerator.php

Zuletzt modifiziert: 09.10.2024, 12:56 - Dateigröße: 13.83 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\Generator;
 013   
 014  use Symfony\Component\Routing\RouteCollection;
 015  use Symfony\Component\Routing\RequestContext;
 016  use Symfony\Component\Routing\Exception\InvalidParameterException;
 017  use Symfony\Component\Routing\Exception\RouteNotFoundException;
 018  use Symfony\Component\Routing\Exception\MissingMandatoryParametersException;
 019  use Psr\Log\LoggerInterface;
 020   
 021  /**
 022   * UrlGenerator can generate a URL or a path for any route in the RouteCollection
 023   * based on the passed parameters.
 024   *
 025   * @author Fabien Potencier <fabien@symfony.com>
 026   * @author Tobias Schultze <http://tobion.de>
 027   */
 028  class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInterface
 029  {
 030      /**
 031       * @var RouteCollection
 032       */
 033      protected $routes;
 034   
 035      /**
 036       * @var RequestContext
 037       */
 038      protected $context;
 039   
 040      /**
 041       * @var bool|null
 042       */
 043      protected $strictRequirements = true;
 044   
 045      /**
 046       * @var LoggerInterface|null
 047       */
 048      protected $logger;
 049   
 050      /**
 051       * This array defines the characters (besides alphanumeric ones) that will not be percent-encoded in the path segment of the generated URL.
 052       *
 053       * PHP's rawurlencode() encodes all chars except "a-zA-Z0-9-._~" according to RFC 3986. But we want to allow some chars
 054       * to be used in their literal form (reasons below). Other chars inside the path must of course be encoded, e.g.
 055       * "?" and "#" (would be interpreted wrongly as query and fragment identifier),
 056       * "'" and """ (are used as delimiters in HTML).
 057       */
 058      protected $decodedChars = array(
 059          // the slash can be used to designate a hierarchical structure and we want allow using it with this meaning
 060          // some webservers don't allow the slash in encoded form in the path for security reasons anyway
 061          // see http://stackoverflow.com/questions/4069002/http-400-if-2f-part-of-get-url-in-jboss
 062          '%2F' => '/',
 063          // the following chars are general delimiters in the URI specification but have only special meaning in the authority component
 064          // so they can safely be used in the path in unencoded form
 065          '%40' => '@',
 066          '%3A' => ':',
 067          // these chars are only sub-delimiters that have no predefined meaning and can therefore be used literally
 068          // so URI producing applications can use these chars to delimit subcomponents in a path segment without being encoded for better readability
 069          '%3B' => ';',
 070          '%2C' => ',',
 071          '%3D' => '=',
 072          '%2B' => '+',
 073          '%21' => '!',
 074          '%2A' => '*',
 075          '%7C' => '|',
 076      );
 077   
 078      /**
 079       * Constructor.
 080       *
 081       * @param RouteCollection      $routes  A RouteCollection instance
 082       * @param RequestContext       $context The context
 083       * @param LoggerInterface|null $logger  A logger instance
 084       */
 085      public function __construct(RouteCollection $routes, RequestContext $context, LoggerInterface $logger = null)
 086      {
 087          $this->routes = $routes;
 088          $this->context = $context;
 089          $this->logger = $logger;
 090      }
 091   
 092      /**
 093       * {@inheritdoc}
 094       */
 095      public function setContext(RequestContext $context)
 096      {
 097          $this->context = $context;
 098      }
 099   
 100      /**
 101       * {@inheritdoc}
 102       */
 103      public function getContext()
 104      {
 105          return $this->context;
 106      }
 107   
 108      /**
 109       * {@inheritdoc}
 110       */
 111      public function setStrictRequirements($enabled)
 112      {
 113          $this->strictRequirements = null === $enabled ? null : (bool) $enabled;
 114      }
 115   
 116      /**
 117       * {@inheritdoc}
 118       */
 119      public function isStrictRequirements()
 120      {
 121          return $this->strictRequirements;
 122      }
 123   
 124      /**
 125       * {@inheritdoc}
 126       */
 127      public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH)
 128      {
 129          if (null === $route = $this->routes->get($name)) {
 130              throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name));
 131          }
 132   
 133          // the Route has a cache of its own and is not recompiled as long as it does not get modified
 134          $compiledRoute = $route->compile();
 135   
 136          return $this->doGenerate($compiledRoute->getVariables(), $route->getDefaults(), $route->getRequirements(), $compiledRoute->getTokens(), $parameters, $name, $referenceType, $compiledRoute->getHostTokens(), $route->getSchemes());
 137      }
 138   
 139      /**
 140       * @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route
 141       * @throws InvalidParameterException           When a parameter value for a placeholder is not correct because
 142       *                                             it does not match the requirement
 143       */
 144      protected function doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens, array $requiredSchemes = array())
 145      {
 146          if (is_bool($referenceType) || is_string($referenceType)) {
 147              @trigger_error('The hardcoded value you are using for the $referenceType argument of the '.__CLASS__.'::generate method is deprecated since version 2.8 and will not be supported anymore in 3.0. Use the constants defined in the UrlGeneratorInterface instead.', E_USER_DEPRECATED);
 148   
 149              if (true === $referenceType) {
 150                  $referenceType = self::ABSOLUTE_URL;
 151              } elseif (false === $referenceType) {
 152                  $referenceType = self::ABSOLUTE_PATH;
 153              } elseif ('relative' === $referenceType) {
 154                  $referenceType = self::RELATIVE_PATH;
 155              } elseif ('network' === $referenceType) {
 156                  $referenceType = self::NETWORK_PATH;
 157              }
 158          }
 159   
 160          $variables = array_flip($variables);
 161          $mergedParams = array_replace($defaults, $this->context->getParameters(), $parameters);
 162   
 163          // all params must be given
 164          if ($diff = array_diff_key($variables, $mergedParams)) {
 165              throw new MissingMandatoryParametersException(sprintf('Some mandatory parameters are missing ("%s") to generate a URL for route "%s".', implode('", "', array_keys($diff)), $name));
 166          }
 167   
 168          $url = '';
 169          $optional = true;
 170          foreach ($tokens as $token) {
 171              if ('variable' === $token[0]) {
 172                  if (!$optional || !array_key_exists($token[3], $defaults) || null !== $mergedParams[$token[3]] && (string) $mergedParams[$token[3]] !== (string) $defaults[$token[3]]) {
 173                      // check requirement
 174                      if (null !== $this->strictRequirements && !preg_match('#^'.$token[2].'$#', $mergedParams[$token[3]])) {
 175                          $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]]);
 176                          if ($this->strictRequirements) {
 177                              throw new InvalidParameterException($message);
 178                          }
 179   
 180                          if ($this->logger) {
 181                              $this->logger->error($message);
 182                          }
 183   
 184                          return;
 185                      }
 186   
 187                      $url = $token[1].$mergedParams[$token[3]].$url;
 188                      $optional = false;
 189                  }
 190              } else {
 191                  // static text
 192                  $url = $token[1].$url;
 193                  $optional = false;
 194              }
 195          }
 196   
 197          if ('' === $url) {
 198              $url = '/';
 199          }
 200   
 201          // the contexts base URL is already encoded (see Symfony\Component\HttpFoundation\Request)
 202          $url = strtr(rawurlencode($url), $this->decodedChars);
 203   
 204          // the path segments "." and ".." are interpreted as relative reference when resolving a URI; see http://tools.ietf.org/html/rfc3986#section-3.3
 205          // so we need to encode them as they are not used for this purpose here
 206          // otherwise we would generate a URI that, when followed by a user agent (e.g. browser), does not match this route
 207          $url = strtr($url, array('/../' => '/%2E%2E/', '/./' => '/%2E/'));
 208          if ('/..' === substr($url, -3)) {
 209              $url = substr($url, 0, -2).'%2E%2E';
 210          } elseif ('/.' === substr($url, -2)) {
 211              $url = substr($url, 0, -1).'%2E';
 212          }
 213   
 214          $schemeAuthority = '';
 215          if ($host = $this->context->getHost()) {
 216              $scheme = $this->context->getScheme();
 217   
 218              if ($requiredSchemes) {
 219                  if (!in_array($scheme, $requiredSchemes, true)) {
 220                      $referenceType = self::ABSOLUTE_URL;
 221                      $scheme = current($requiredSchemes);
 222                  }
 223              } elseif (isset($requirements['_scheme']) && ($req = strtolower($requirements['_scheme'])) && $scheme !== $req) {
 224                  // We do this for BC; to be removed if _scheme is not supported anymore
 225                  $referenceType = self::ABSOLUTE_URL;
 226                  $scheme = $req;
 227              }
 228   
 229              if ($hostTokens) {
 230                  $routeHost = '';
 231                  foreach ($hostTokens as $token) {
 232                      if ('variable' === $token[0]) {
 233                          if (null !== $this->strictRequirements && !preg_match('#^'.$token[2].'$#i', $mergedParams[$token[3]])) {
 234                              $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]]);
 235   
 236                              if ($this->strictRequirements) {
 237                                  throw new InvalidParameterException($message);
 238                              }
 239   
 240                              if ($this->logger) {
 241                                  $this->logger->error($message);
 242                              }
 243   
 244                              return;
 245                          }
 246   
 247                          $routeHost = $token[1].$mergedParams[$token[3]].$routeHost;
 248                      } else {
 249                          $routeHost = $token[1].$routeHost;
 250                      }
 251                  }
 252   
 253                  if ($routeHost !== $host) {
 254                      $host = $routeHost;
 255                      if (self::ABSOLUTE_URL !== $referenceType) {
 256                          $referenceType = self::NETWORK_PATH;
 257                      }
 258                  }
 259              }
 260   
 261              if (self::ABSOLUTE_URL === $referenceType || self::NETWORK_PATH === $referenceType) {
 262                  $port = '';
 263                  if ('http' === $scheme && 80 != $this->context->getHttpPort()) {
 264                      $port = ':'.$this->context->getHttpPort();
 265                  } elseif ('https' === $scheme && 443 != $this->context->getHttpsPort()) {
 266                      $port = ':'.$this->context->getHttpsPort();
 267                  }
 268   
 269                  $schemeAuthority = self::NETWORK_PATH === $referenceType ? '//' : "$scheme://";
 270                  $schemeAuthority .= $host.$port;
 271              }
 272          }
 273   
 274          if (self::RELATIVE_PATH === $referenceType) {
 275              $url = self::getRelativePath($this->context->getPathInfo(), $url);
 276          } else {
 277              $url = $schemeAuthority.$this->context->getBaseUrl().$url;
 278          }
 279   
 280          // add a query string if needed
 281          $extra = array_udiff_assoc(array_diff_key($parameters, $variables), $defaults, function ($a, $b) {
 282              return $a == $b ? 0 : 1;
 283          });
 284   
 285          if ($extra && $query = http_build_query($extra, '', '&')) {
 286              // "/" and "?" can be left decoded for better user experience, see
 287              // http://tools.ietf.org/html/rfc3986#section-3.4
 288              $url .= '?'.strtr($query, array('%2F' => '/'));
 289          }
 290   
 291          return $url;
 292      }
 293   
 294      /**
 295       * Returns the target path as relative reference from the base path.
 296       *
 297       * Only the URIs path component (no schema, host etc.) is relevant and must be given, starting with a slash.
 298       * Both paths must be absolute and not contain relative parts.
 299       * Relative URLs from one resource to another are useful when generating self-contained downloadable document archives.
 300       * Furthermore, they can be used to reduce the link size in documents.
 301       *
 302       * Example target paths, given a base path of "/a/b/c/d":
 303       * - "/a/b/c/d"     -> ""
 304       * - "/a/b/c/"      -> "./"
 305       * - "/a/b/"        -> "../"
 306       * - "/a/b/c/other" -> "other"
 307       * - "/a/x/y"       -> "../../x/y"
 308       *
 309       * @param string $basePath   The base path
 310       * @param string $targetPath The target path
 311       *
 312       * @return string The relative target path
 313       */
 314      public static function getRelativePath($basePath, $targetPath)
 315      {
 316          if ($basePath === $targetPath) {
 317              return '';
 318          }
 319   
 320          $sourceDirs = explode('/', isset($basePath[0]) && '/' === $basePath[0] ? substr($basePath, 1) : $basePath);
 321          $targetDirs = explode('/', isset($targetPath[0]) && '/' === $targetPath[0] ? substr($targetPath, 1) : $targetPath);
 322          array_pop($sourceDirs);
 323          $targetFile = array_pop($targetDirs);
 324   
 325          foreach ($sourceDirs as $i => $dir) {
 326              if (isset($targetDirs[$i]) && $dir === $targetDirs[$i]) {
 327                  unset($sourceDirs[$i], $targetDirs[$i]);
 328              } else {
 329                  break;
 330              }
 331          }
 332   
 333          $targetDirs[] = $targetFile;
 334          $path = str_repeat('../', count($sourceDirs)).implode('/', $targetDirs);
 335   
 336          // A reference to the same base directory or an empty subdirectory must be prefixed with "./".
 337          // This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used
 338          // as the first segment of a relative-path reference, as it would be mistaken for a scheme name
 339          // (see http://tools.ietf.org/html/rfc3986#section-4.2).
 340          return '' === $path || '/' === $path[0]
 341              || false !== ($colonPos = strpos($path, ':')) && ($colonPos < ($slashPos = strpos($path, '/')) || false === $slashPos)
 342              ? "./$path" : $path;
 343      }
 344  }
 345