[ Index ]

PHP Cross Reference of phpBB-3.2.11-deutsch

title

Body

[close]

/vendor/guzzlehttp/guzzle/src/ -> Url.php (source)

   1  <?php
   2  namespace GuzzleHttp;
   3  
   4  use GuzzleHttp\Ring\Core;
   5  
   6  /**
   7   * Parses and generates URLs based on URL parts
   8   */
   9  class Url
  10  {
  11      private $scheme;
  12      private $host;
  13      private $port;
  14      private $username;
  15      private $password;
  16      private $path = '';
  17      private $fragment;
  18      private static $defaultPorts = ['http' => 80, 'https' => 443, 'ftp' => 21];
  19      private static $pathPattern = '/[^a-zA-Z0-9\-\._~!\$&\'\(\)\*\+,;=%:@\/]+|%(?![A-Fa-f0-9]{2})/';
  20      private static $queryPattern = '/[^a-zA-Z0-9\-\._~!\$\'\(\)\*\+,;%:@\/\?=&]+|%(?![A-Fa-f0-9]{2})/';
  21      /** @var Query|string Query part of the URL */
  22      private $query;
  23  
  24      /**
  25       * Factory method to create a new URL from a URL string
  26       *
  27       * @param string $url Full URL used to create a Url object
  28       *
  29       * @return Url
  30       * @throws \InvalidArgumentException
  31       */
  32      public static function fromString($url)
  33      {
  34          static $defaults = ['scheme' => null, 'host' => null,
  35              'path' => null, 'port' => null, 'query' => null,
  36              'user' => null, 'pass' => null, 'fragment' => null];
  37  
  38          if (false === ($parts = parse_url($url))) {
  39              throw new \InvalidArgumentException('Unable to parse malformed '
  40                  . 'url: ' . $url);
  41          }
  42  
  43          $parts += $defaults;
  44  
  45          // Convert the query string into a Query object
  46          if ($parts['query'] || 0 !== strlen($parts['query'])) {
  47              $parts['query'] = Query::fromString($parts['query']);
  48          }
  49  
  50          return new static($parts['scheme'], $parts['host'], $parts['user'],
  51              $parts['pass'], $parts['port'], $parts['path'], $parts['query'],
  52              $parts['fragment']);
  53      }
  54  
  55      /**
  56       * Build a URL from parse_url parts. The generated URL will be a relative
  57       * URL if a scheme or host are not provided.
  58       *
  59       * @param array $parts Array of parse_url parts
  60       *
  61       * @return string
  62       */
  63      public static function buildUrl(array $parts)
  64      {
  65          $url = $scheme = '';
  66  
  67          if (!empty($parts['scheme'])) {
  68              $scheme = $parts['scheme'];
  69              $url .= $scheme . ':';
  70          }
  71  
  72          if (!empty($parts['host'])) {
  73              $url .= '//';
  74              if (isset($parts['user'])) {
  75                  $url .= $parts['user'];
  76                  if (isset($parts['pass'])) {
  77                      $url .= ':' . $parts['pass'];
  78                  }
  79                  $url .=  '@';
  80              }
  81  
  82              $url .= $parts['host'];
  83  
  84              // Only include the port if it is not the default port of the scheme
  85              if (isset($parts['port']) &&
  86                  (!isset(self::$defaultPorts[$scheme]) ||
  87                   $parts['port'] != self::$defaultPorts[$scheme])
  88              ) {
  89                  $url .= ':' . $parts['port'];
  90              }
  91          }
  92  
  93          // Add the path component if present
  94          if (isset($parts['path']) && strlen($parts['path'])) {
  95              // Always ensure that the path begins with '/' if set and something
  96              // is before the path
  97              if (!empty($parts['host']) && $parts['path'][0] != '/') {
  98                  $url .= '/';
  99              }
 100              $url .= $parts['path'];
 101          }
 102  
 103          // Add the query string if present
 104          if (isset($parts['query'])) {
 105              $queryStr = (string) $parts['query'];
 106              if ($queryStr || $queryStr === '0') {
 107                  $url .= '?' . $queryStr;
 108              }
 109          }
 110  
 111          // Ensure that # is only added to the url if fragment contains anything.
 112          if (isset($parts['fragment'])) {
 113              $url .= '#' . $parts['fragment'];
 114          }
 115  
 116          return $url;
 117      }
 118  
 119      /**
 120       * Create a new URL from URL parts
 121       *
 122       * @param string             $scheme   Scheme of the URL
 123       * @param string             $host     Host of the URL
 124       * @param string             $username Username of the URL
 125       * @param string             $password Password of the URL
 126       * @param int                $port     Port of the URL
 127       * @param string             $path     Path of the URL
 128       * @param Query|array|string $query    Query string of the URL
 129       * @param string             $fragment Fragment of the URL
 130       */
 131      public function __construct(
 132          $scheme,
 133          $host,
 134          $username = null,
 135          $password = null,
 136          $port = null,
 137          $path = null,
 138          $query = null,
 139          $fragment = null
 140      ) {
 141          $this->scheme = strtolower($scheme);
 142          $this->host = $host;
 143          $this->port = $port;
 144          $this->username = $username;
 145          $this->password = $password;
 146          $this->fragment = $fragment;
 147  
 148          if ($query) {
 149              $this->setQuery($query);
 150          }
 151  
 152          $this->setPath($path);
 153      }
 154  
 155      /**
 156       * Clone the URL
 157       */
 158      public function __clone()
 159      {
 160          if ($this->query instanceof Query) {
 161              $this->query = clone $this->query;
 162          }
 163      }
 164  
 165      /**
 166       * Returns the URL as a URL string
 167       *
 168       * @return string
 169       */
 170      public function __toString()
 171      {
 172          return static::buildUrl($this->getParts());
 173      }
 174  
 175      /**
 176       * Get the parts of the URL as an array
 177       *
 178       * @return array
 179       */
 180      public function getParts()
 181      {
 182          return array(
 183              'scheme'   => $this->scheme,
 184              'user'     => $this->username,
 185              'pass'     => $this->password,
 186              'host'     => $this->host,
 187              'port'     => $this->port,
 188              'path'     => $this->path,
 189              'query'    => $this->query,
 190              'fragment' => $this->fragment,
 191          );
 192      }
 193  
 194      /**
 195       * Set the host of the request.
 196       *
 197       * @param string $host Host to set (e.g. www.yahoo.com, yahoo.com)
 198       *
 199       * @return Url
 200       */
 201      public function setHost($host)
 202      {
 203          if (strpos($host, ':') === false) {
 204              $this->host = $host;
 205          } else {
 206              list($host, $port) = explode(':', $host);
 207              $this->host = $host;
 208              $this->setPort($port);
 209          }
 210      }
 211  
 212      /**
 213       * Get the host part of the URL
 214       *
 215       * @return string
 216       */
 217      public function getHost()
 218      {
 219          return $this->host;
 220      }
 221  
 222      /**
 223       * Set the scheme part of the URL (http, https, ftp, etc.)
 224       *
 225       * @param string $scheme Scheme to set
 226       */
 227      public function setScheme($scheme)
 228      {
 229          // Remove the default port if one is specified
 230          if ($this->port
 231              && isset(self::$defaultPorts[$this->scheme])
 232              && self::$defaultPorts[$this->scheme] == $this->port
 233          ) {
 234              $this->port = null;
 235          }
 236  
 237          $this->scheme = strtolower($scheme);
 238      }
 239  
 240      /**
 241       * Get the scheme part of the URL
 242       *
 243       * @return string
 244       */
 245      public function getScheme()
 246      {
 247          return $this->scheme;
 248      }
 249  
 250      /**
 251       * Set the port part of the URL
 252       *
 253       * @param int $port Port to set
 254       */
 255      public function setPort($port)
 256      {
 257          $this->port = $port;
 258      }
 259  
 260      /**
 261       * Get the port part of the URl.
 262       *
 263       * If no port was set, this method will return the default port for the
 264       * scheme of the URI.
 265       *
 266       * @return int|null
 267       */
 268      public function getPort()
 269      {
 270          if ($this->port) {
 271              return $this->port;
 272          } elseif (isset(self::$defaultPorts[$this->scheme])) {
 273              return self::$defaultPorts[$this->scheme];
 274          }
 275  
 276          return null;
 277      }
 278  
 279      /**
 280       * Set the path part of the URL.
 281       *
 282       * The provided URL is URL encoded as necessary.
 283       *
 284       * @param string $path Path string to set
 285       */
 286      public function setPath($path)
 287      {
 288          $this->path = self::encodePath($path);
 289      }
 290  
 291      /**
 292       * Removes dot segments from a URL
 293       * @link http://tools.ietf.org/html/rfc3986#section-5.2.4
 294       */
 295      public function removeDotSegments()
 296      {
 297          static $noopPaths = ['' => true, '/' => true, '*' => true];
 298          static $ignoreSegments = ['.' => true, '..' => true];
 299  
 300          if (isset($noopPaths[$this->path])) {
 301              return;
 302          }
 303  
 304          $results = [];
 305          $segments = $this->getPathSegments();
 306          foreach ($segments as $segment) {
 307              if ($segment == '..') {
 308                  array_pop($results);
 309              } elseif (!isset($ignoreSegments[$segment])) {
 310                  $results[] = $segment;
 311              }
 312          }
 313  
 314          $newPath = implode('/', $results);
 315  
 316          // Add the leading slash if necessary
 317          if (substr($this->path, 0, 1) === '/' &&
 318              substr($newPath, 0, 1) !== '/'
 319          ) {
 320              $newPath = '/' . $newPath;
 321          }
 322  
 323          // Add the trailing slash if necessary
 324          if ($newPath != '/' && isset($ignoreSegments[end($segments)])) {
 325              $newPath .= '/';
 326          }
 327  
 328          $this->path = $newPath;
 329      }
 330  
 331      /**
 332       * Add a relative path to the currently set path.
 333       *
 334       * @param string $relativePath Relative path to add
 335       */
 336      public function addPath($relativePath)
 337      {
 338          if ($relativePath != '/' &&
 339              is_string($relativePath) &&
 340              strlen($relativePath) > 0
 341          ) {
 342              // Add a leading slash if needed
 343              if ($relativePath[0] !== '/' &&
 344                  substr($this->path, -1, 1) !== '/'
 345              ) {
 346                  $relativePath = '/' . $relativePath;
 347              }
 348  
 349              $this->setPath($this->path . $relativePath);
 350          }
 351      }
 352  
 353      /**
 354       * Get the path part of the URL
 355       *
 356       * @return string
 357       */
 358      public function getPath()
 359      {
 360          return $this->path;
 361      }
 362  
 363      /**
 364       * Get the path segments of the URL as an array
 365       *
 366       * @return array
 367       */
 368      public function getPathSegments()
 369      {
 370          return explode('/', $this->path);
 371      }
 372  
 373      /**
 374       * Set the password part of the URL
 375       *
 376       * @param string $password Password to set
 377       */
 378      public function setPassword($password)
 379      {
 380          $this->password = $password;
 381      }
 382  
 383      /**
 384       * Get the password part of the URL
 385       *
 386       * @return null|string
 387       */
 388      public function getPassword()
 389      {
 390          return $this->password;
 391      }
 392  
 393      /**
 394       * Set the username part of the URL
 395       *
 396       * @param string $username Username to set
 397       */
 398      public function setUsername($username)
 399      {
 400          $this->username = $username;
 401      }
 402  
 403      /**
 404       * Get the username part of the URl
 405       *
 406       * @return null|string
 407       */
 408      public function getUsername()
 409      {
 410          return $this->username;
 411      }
 412  
 413      /**
 414       * Get the query part of the URL as a Query object
 415       *
 416       * @return Query
 417       */
 418      public function getQuery()
 419      {
 420          // Convert the query string to a query object if not already done.
 421          if (!$this->query instanceof Query) {
 422              $this->query = $this->query === null
 423                  ? new Query()
 424                  : Query::fromString($this->query);
 425          }
 426  
 427          return $this->query;
 428      }
 429  
 430      /**
 431       * Set the query part of the URL.
 432       *
 433       * You may provide a query string as a string and pass $rawString as true
 434       * to provide a query string that is not parsed until a call to getQuery()
 435       * is made. Setting a raw query string will still encode invalid characters
 436       * in a query string.
 437       *
 438       * @param Query|string|array $query Query string value to set. Can
 439       *     be a string that will be parsed into a Query object, an array
 440       *     of key value pairs, or a Query object.
 441       * @param bool $rawString Set to true when providing a raw query string.
 442       *
 443       * @throws \InvalidArgumentException
 444       */
 445      public function setQuery($query, $rawString = false)
 446      {
 447          if ($query instanceof Query) {
 448              $this->query = $query;
 449          } elseif (is_string($query)) {
 450              if (!$rawString) {
 451                  $this->query = Query::fromString($query);
 452              } else {
 453                  // Ensure the query does not have illegal characters.
 454                  $this->query = preg_replace_callback(
 455                      self::$queryPattern,
 456                      [__CLASS__, 'encodeMatch'],
 457                      $query
 458                  );
 459              }
 460  
 461          } elseif (is_array($query)) {
 462              $this->query = new Query($query);
 463          } else {
 464              throw new \InvalidArgumentException('Query must be a Query, '
 465                  . 'array, or string. Got ' . Core::describeType($query));
 466          }
 467      }
 468  
 469      /**
 470       * Get the fragment part of the URL
 471       *
 472       * @return null|string
 473       */
 474      public function getFragment()
 475      {
 476          return $this->fragment;
 477      }
 478  
 479      /**
 480       * Set the fragment part of the URL
 481       *
 482       * @param string $fragment Fragment to set
 483       */
 484      public function setFragment($fragment)
 485      {
 486          $this->fragment = $fragment;
 487      }
 488  
 489      /**
 490       * Check if this is an absolute URL
 491       *
 492       * @return bool
 493       */
 494      public function isAbsolute()
 495      {
 496          return $this->scheme && $this->host;
 497      }
 498  
 499      /**
 500       * Combine the URL with another URL and return a new URL instance.
 501       *
 502       * Follows the rules specific in RFC 3986 section 5.4.
 503       *
 504       * @param string $url Relative URL to combine with
 505       *
 506       * @return Url
 507       * @throws \InvalidArgumentException
 508       * @link http://tools.ietf.org/html/rfc3986#section-5.4
 509       */
 510      public function combine($url)
 511      {
 512          $url = static::fromString($url);
 513  
 514          // Use the more absolute URL as the base URL
 515          if (!$this->isAbsolute() && $url->isAbsolute()) {
 516              $url = $url->combine($this);
 517          }
 518  
 519          $parts = $url->getParts();
 520  
 521          // Passing a URL with a scheme overrides everything
 522          if ($parts['scheme']) {
 523              return clone $url;
 524          }
 525  
 526          // Setting a host overrides the entire rest of the URL
 527          if ($parts['host']) {
 528              return new static(
 529                  $this->scheme,
 530                  $parts['host'],
 531                  $parts['user'],
 532                  $parts['pass'],
 533                  $parts['port'],
 534                  $parts['path'],
 535                  $parts['query'] instanceof Query
 536                      ? clone $parts['query']
 537                      : $parts['query'],
 538                  $parts['fragment']
 539              );
 540          }
 541  
 542          if (!$parts['path'] && $parts['path'] !== '0') {
 543              // The relative URL has no path, so check if it is just a query
 544              $path = $this->path ?: '';
 545              $query = $parts['query'] ?: $this->query;
 546          } else {
 547              $query = $parts['query'];
 548              if ($parts['path'][0] == '/' || !$this->path) {
 549                  // Overwrite the existing path if the rel path starts with "/"
 550                  $path = $parts['path'];
 551              } else {
 552                  // If the relative URL does not have a path or the base URL
 553                  // path does not end in a "/" then overwrite the existing path
 554                  // up to the last "/"
 555                  $path = substr($this->path, 0, strrpos($this->path, '/') + 1) . $parts['path'];
 556              }
 557          }
 558  
 559          $result = new self(
 560              $this->scheme,
 561              $this->host,
 562              $this->username,
 563              $this->password,
 564              $this->port,
 565              $path,
 566              $query instanceof Query ? clone $query : $query,
 567              $parts['fragment']
 568          );
 569  
 570          if ($path) {
 571              $result->removeDotSegments();
 572          }
 573  
 574          return $result;
 575      }
 576  
 577      /**
 578       * Encodes the path part of a URL without double-encoding percent-encoded
 579       * key value pairs.
 580       *
 581       * @param string $path Path to encode
 582       *
 583       * @return string
 584       */
 585      public static function encodePath($path)
 586      {
 587          static $cb = [__CLASS__, 'encodeMatch'];
 588          return preg_replace_callback(self::$pathPattern, $cb, $path);
 589      }
 590  
 591      private static function encodeMatch(array $match)
 592      {
 593          return rawurlencode($match[0]);
 594      }
 595  }


Generated: Wed Nov 11 20:33:01 2020 Cross-referenced by PHPXref 0.7.1