ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Uri.php
Go to the documentation of this file.
1 <?php
2 namespace GuzzleHttp\Psr7;
3 
5 
13 class Uri implements UriInterface
14 {
21  const HTTP_DEFAULT_HOST = 'localhost';
22 
23  private static $defaultPorts = [
24  'http' => 80,
25  'https' => 443,
26  'ftp' => 21,
27  'gopher' => 70,
28  'nntp' => 119,
29  'news' => 119,
30  'telnet' => 23,
31  'tn3270' => 23,
32  'imap' => 143,
33  'pop' => 110,
34  'ldap' => 389,
35  ];
36 
37  private static $charUnreserved = 'a-zA-Z0-9_\-\.~';
38  private static $charSubDelims = '!\$&\'\(\)\*\+,;=';
39  private static $replaceQuery = ['=' => '%3D', '&' => '%26'];
40 
42  private $scheme = '';
43 
45  private $userInfo = '';
46 
48  private $host = '';
49 
51  private $port;
52 
54  private $path = '';
55 
57  private $query = '';
58 
60  private $fragment = '';
61 
65  public function __construct($uri = '')
66  {
67  // weak type check to also accept null until we can add scalar type hints
68  if ($uri != '') {
69  $parts = parse_url($uri);
70  if ($parts === false) {
71  throw new \InvalidArgumentException("Unable to parse URI: $uri");
72  }
73  $this->applyParts($parts);
74  }
75  }
76 
77  public function __toString()
78  {
79  return self::composeComponents(
80  $this->scheme,
81  $this->getAuthority(),
82  $this->path,
83  $this->query,
84  $this->fragment
85  );
86  }
87 
115  {
116  $uri = '';
117 
118  // weak type checks to also accept null until we can add scalar type hints
119  if ($scheme != '') {
120  $uri .= $scheme . ':';
121  }
122 
123  if ($authority != ''|| $scheme === 'file') {
124  $uri .= '//' . $authority;
125  }
126 
127  $uri .= $path;
128 
129  if ($query != '') {
130  $uri .= '?' . $query;
131  }
132 
133  if ($fragment != '') {
134  $uri .= '#' . $fragment;
135  }
136 
137  return $uri;
138  }
139 
150  public static function isDefaultPort(UriInterface $uri)
151  {
152  return $uri->getPort() === null
153  || (isset(self::$defaultPorts[$uri->getScheme()]) && $uri->getPort() === self::$defaultPorts[$uri->getScheme()]);
154  }
155 
174  public static function isAbsolute(UriInterface $uri)
175  {
176  return $uri->getScheme() !== '';
177  }
178 
189  public static function isNetworkPathReference(UriInterface $uri)
190  {
191  return $uri->getScheme() === '' && $uri->getAuthority() !== '';
192  }
193 
204  public static function isAbsolutePathReference(UriInterface $uri)
205  {
206  return $uri->getScheme() === ''
207  && $uri->getAuthority() === ''
208  && isset($uri->getPath()[0])
209  && $uri->getPath()[0] === '/';
210  }
211 
222  public static function isRelativePathReference(UriInterface $uri)
223  {
224  return $uri->getScheme() === ''
225  && $uri->getAuthority() === ''
226  && (!isset($uri->getPath()[0]) || $uri->getPath()[0] !== '/');
227  }
228 
242  public static function isSameDocumentReference(UriInterface $uri, UriInterface $base = null)
243  {
244  if ($base !== null) {
245  $uri = UriResolver::resolve($base, $uri);
246 
247  return ($uri->getScheme() === $base->getScheme())
248  && ($uri->getAuthority() === $base->getAuthority())
249  && ($uri->getPath() === $base->getPath())
250  && ($uri->getQuery() === $base->getQuery());
251  }
252 
253  return $uri->getScheme() === '' && $uri->getAuthority() === '' && $uri->getPath() === '' && $uri->getQuery() === '';
254  }
255 
266  public static function removeDotSegments($path)
267  {
269  }
270 
282  public static function resolve(UriInterface $base, $rel)
283  {
284  if (!($rel instanceof UriInterface)) {
285  $rel = new self($rel);
286  }
287 
288  return UriResolver::resolve($base, $rel);
289  }
290 
302  public static function withoutQueryValue(UriInterface $uri, $key)
303  {
304  $current = $uri->getQuery();
305  if ($current === '') {
306  return $uri;
307  }
308 
309  $decodedKey = rawurldecode($key);
310  $result = array_filter(explode('&', $current), function ($part) use ($decodedKey) {
311  return rawurldecode(explode('=', $part)[0]) !== $decodedKey;
312  });
313 
314  return $uri->withQuery(implode('&', $result));
315  }
316 
332  public static function withQueryValue(UriInterface $uri, $key, $value)
333  {
334  $current = $uri->getQuery();
335 
336  if ($current === '') {
337  $result = [];
338  } else {
339  $decodedKey = rawurldecode($key);
340  $result = array_filter(explode('&', $current), function ($part) use ($decodedKey) {
341  return rawurldecode(explode('=', $part)[0]) !== $decodedKey;
342  });
343  }
344 
345  // Query string separators ("=", "&") within the key or value need to be encoded
346  // (while preventing double-encoding) before setting the query string. All other
347  // chars that need percent-encoding will be encoded by withQuery().
348  $key = strtr($key, self::$replaceQuery);
349 
350  if ($value !== null) {
351  $result[] = $key . '=' . strtr($value, self::$replaceQuery);
352  } else {
353  $result[] = $key;
354  }
355 
356  return $uri->withQuery(implode('&', $result));
357  }
358 
369  public static function fromParts(array $parts)
370  {
371  $uri = new self();
372  $uri->applyParts($parts);
373  $uri->validateState();
374 
375  return $uri;
376  }
377 
378  public function getScheme()
379  {
380  return $this->scheme;
381  }
382 
383  public function getAuthority()
384  {
386  if ($this->userInfo !== '') {
387  $authority = $this->userInfo . '@' . $authority;
388  }
389 
390  if ($this->port !== null) {
391  $authority .= ':' . $this->port;
392  }
393 
394  return $authority;
395  }
396 
397  public function getUserInfo()
398  {
399  return $this->userInfo;
400  }
401 
402  public function getHost()
403  {
404  return $this->host;
405  }
406 
407  public function getPort()
408  {
409  return $this->port;
410  }
411 
412  public function getPath()
413  {
414  return $this->path;
415  }
416 
417  public function getQuery()
418  {
419  return $this->query;
420  }
421 
422  public function getFragment()
423  {
424  return $this->fragment;
425  }
426 
427  public function withScheme($scheme)
428  {
429  $scheme = $this->filterScheme($scheme);
430 
431  if ($this->scheme === $scheme) {
432  return $this;
433  }
434 
435  $new = clone $this;
436  $new->scheme = $scheme;
437  $new->removeDefaultPort();
438  $new->validateState();
439 
440  return $new;
441  }
442 
443  public function withUserInfo($user, $password = null)
444  {
445  $info = $user;
446  if ($password != '') {
447  $info .= ':' . $password;
448  }
449 
450  if ($this->userInfo === $info) {
451  return $this;
452  }
453 
454  $new = clone $this;
455  $new->userInfo = $info;
456  $new->validateState();
457 
458  return $new;
459  }
460 
461  public function withHost($host)
462  {
463  $host = $this->filterHost($host);
464 
465  if ($this->host === $host) {
466  return $this;
467  }
468 
469  $new = clone $this;
470  $new->host = $host;
471  $new->validateState();
472 
473  return $new;
474  }
475 
476  public function withPort($port)
477  {
478  $port = $this->filterPort($port);
479 
480  if ($this->port === $port) {
481  return $this;
482  }
483 
484  $new = clone $this;
485  $new->port = $port;
486  $new->removeDefaultPort();
487  $new->validateState();
488 
489  return $new;
490  }
491 
492  public function withPath($path)
493  {
494  $path = $this->filterPath($path);
495 
496  if ($this->path === $path) {
497  return $this;
498  }
499 
500  $new = clone $this;
501  $new->path = $path;
502  $new->validateState();
503 
504  return $new;
505  }
506 
507  public function withQuery($query)
508  {
510 
511  if ($this->query === $query) {
512  return $this;
513  }
514 
515  $new = clone $this;
516  $new->query = $query;
517 
518  return $new;
519  }
520 
521  public function withFragment($fragment)
522  {
524 
525  if ($this->fragment === $fragment) {
526  return $this;
527  }
528 
529  $new = clone $this;
530  $new->fragment = $fragment;
531 
532  return $new;
533  }
534 
540  private function applyParts(array $parts)
541  {
542  $this->scheme = isset($parts['scheme'])
543  ? $this->filterScheme($parts['scheme'])
544  : '';
545  $this->userInfo = isset($parts['user']) ? $parts['user'] : '';
546  $this->host = isset($parts['host'])
547  ? $this->filterHost($parts['host'])
548  : '';
549  $this->port = isset($parts['port'])
550  ? $this->filterPort($parts['port'])
551  : null;
552  $this->path = isset($parts['path'])
553  ? $this->filterPath($parts['path'])
554  : '';
555  $this->query = isset($parts['query'])
556  ? $this->filterQueryAndFragment($parts['query'])
557  : '';
558  $this->fragment = isset($parts['fragment'])
559  ? $this->filterQueryAndFragment($parts['fragment'])
560  : '';
561  if (isset($parts['pass'])) {
562  $this->userInfo .= ':' . $parts['pass'];
563  }
564 
565  $this->removeDefaultPort();
566  }
567 
575  private function filterScheme($scheme)
576  {
577  if (!is_string($scheme)) {
578  throw new \InvalidArgumentException('Scheme must be a string');
579  }
580 
581  return strtolower($scheme);
582  }
583 
591  private function filterHost($host)
592  {
593  if (!is_string($host)) {
594  throw new \InvalidArgumentException('Host must be a string');
595  }
596 
597  return strtolower($host);
598  }
599 
607  private function filterPort($port)
608  {
609  if ($port === null) {
610  return null;
611  }
612 
613  $port = (int) $port;
614  if (1 > $port || 0xffff < $port) {
615  throw new \InvalidArgumentException(
616  sprintf('Invalid port: %d. Must be between 1 and 65535', $port)
617  );
618  }
619 
620  return $port;
621  }
622 
623  private function removeDefaultPort()
624  {
625  if ($this->port !== null && self::isDefaultPort($this)) {
626  $this->port = null;
627  }
628  }
629 
639  private function filterPath($path)
640  {
641  if (!is_string($path)) {
642  throw new \InvalidArgumentException('Path must be a string');
643  }
644 
645  return preg_replace_callback(
646  '/(?:[^' . self::$charUnreserved . self::$charSubDelims . '%:@\/]++|%(?![A-Fa-f0-9]{2}))/',
647  [$this, 'rawurlencodeMatchZero'],
648  $path
649  );
650  }
651 
661  private function filterQueryAndFragment($str)
662  {
663  if (!is_string($str)) {
664  throw new \InvalidArgumentException('Query and fragment must be a string');
665  }
666 
667  return preg_replace_callback(
668  '/(?:[^' . self::$charUnreserved . self::$charSubDelims . '%:@\/\?]++|%(?![A-Fa-f0-9]{2}))/',
669  [$this, 'rawurlencodeMatchZero'],
670  $str
671  );
672  }
673 
674  private function rawurlencodeMatchZero(array $match)
675  {
676  return rawurlencode($match[0]);
677  }
678 
679  private function validateState()
680  {
681  if ($this->host === '' && ($this->scheme === 'http' || $this->scheme === 'https')) {
682  $this->host = self::HTTP_DEFAULT_HOST;
683  }
684 
685  if ($this->getAuthority() === '') {
686  if (0 === strpos($this->path, '//')) {
687  throw new \InvalidArgumentException('The path of a URI without an authority must not start with two slashes "//"');
688  }
689  if ($this->scheme === '' && false !== strpos(explode('/', $this->path, 2)[0], ':')) {
690  throw new \InvalidArgumentException('A relative URI must not have a path beginning with a segment containing a colon');
691  }
692  } elseif (isset($this->path[0]) && $this->path[0] !== '/') {
693  @trigger_error(
694  'The path of a URI with an authority must start with a slash "/" or be empty. Automagically fixing the URI ' .
695  'by adding a leading slash to the path is deprecated since version 1.4 and will throw an exception instead.',
696  E_USER_DEPRECATED
697  );
698  $this->path = '/'. $this->path;
699  //throw new \InvalidArgumentException('The path of a URI with an authority must start with a slash "/" or be empty');
700  }
701  }
702 }
filterHost($host)
Definition: Uri.php:591
withUserInfo($user, $password=null)
Return an instance with the specified user information.
Definition: Uri.php:443
static isSameDocumentReference(UriInterface $uri, UriInterface $base=null)
Whether the URI is a same-document reference.
Definition: Uri.php:242
static $defaultPorts
Definition: Uri.php:23
static removeDotSegments($path)
Removes dot segments from a path and returns the new path.
Definition: Uri.php:266
getUserInfo()
Retrieve the user information component of the URI.
Definition: Uri.php:397
static isAbsolute(UriInterface $uri)
Whether the URI is absolute, i.e.
Definition: Uri.php:174
static removeDotSegments($path)
Removes dot segments from a path and returns the new path.
Definition: UriResolver.php:23
$result
withQuery($query)
Return an instance with the specified query string.
Definition: Uri.php:507
static static $charUnreserved
Definition: Uri.php:37
withPort($port)
Return an instance with the specified port.
Definition: Uri.php:476
withPath($path)
Return an instance with the specified path.
Definition: Uri.php:492
Value object representing a URI.
filterScheme($scheme)
Definition: Uri.php:575
static resolve(UriInterface $base, UriInterface $rel)
Converts the relative URI into a new URI that is resolved against the base URI.
Definition: UriResolver.php:62
withScheme($scheme)
Return an instance with the specified scheme.
Definition: Uri.php:427
withQuery($query)
Return an instance with the specified query string.
withFragment($fragment)
Return an instance with the specified URI fragment.
Definition: Uri.php:521
PSR-7 URI implementation.
Definition: Uri.php:13
filterPort($port)
Definition: Uri.php:607
getScheme()
Retrieve the scheme component of the URI.
static isNetworkPathReference(UriInterface $uri)
Whether the URI is a network-path reference.
Definition: Uri.php:189
getPort()
Retrieve the port component of the URI.
Definition: Uri.php:407
$base
Definition: index.php:4
static isRelativePathReference(UriInterface $uri)
Whether the URI is a relative-path reference.
Definition: Uri.php:222
filterPath($path)
Filters the path of a URI.
Definition: Uri.php:639
static withQueryValue(UriInterface $uri, $key, $value)
Creates a new URI with a specific query string value.
Definition: Uri.php:332
static fromParts(array $parts)
Creates a URI from a hash of parse_url components.
Definition: Uri.php:369
filterQueryAndFragment($str)
Filters the query string or fragment of a URI.
Definition: Uri.php:661
applyParts(array $parts)
Apply parse_url parts to a URI.
Definition: Uri.php:540
getAuthority()
Retrieve the authority component of the URI.
const HTTP_DEFAULT_HOST
Absolute http and https URIs require a host per RFC 7230 Section 2.7 but in generic URIs the host can...
Definition: Uri.php:21
getScheme()
Retrieve the scheme component of the URI.
Definition: Uri.php:378
getPath()
Retrieve the path component of the URI.
static isAbsolutePathReference(UriInterface $uri)
Whether the URI is a absolute-path reference.
Definition: Uri.php:204
getPort()
Retrieve the port component of the URI.
static resolve(UriInterface $base, $rel)
Converts the relative URI into a new URI that is resolved against the base URI.
Definition: Uri.php:282
$user
Definition: migrateto20.php:57
static $replaceQuery
Definition: Uri.php:39
$password
Definition: cron.php:14
__construct($uri='')
Definition: Uri.php:65
getQuery()
Retrieve the query string of the URI.
Definition: Uri.php:417
getHost()
Retrieve the host component of the URI.
Definition: Uri.php:402
withHost($host)
Return an instance with the specified host.
Definition: Uri.php:461
static composeComponents($scheme, $authority, $path, $query, $fragment)
Composes a URI reference string from its various components.
Definition: Uri.php:114
rawurlencodeMatchZero(array $match)
Definition: Uri.php:674
getAuthority()
Retrieve the authority component of the URI.
Definition: Uri.php:383
__toString()
Return the string representation as a URI reference.
Definition: Uri.php:77
$info
Definition: index.php:5
static withoutQueryValue(UriInterface $uri, $key)
Creates a new URI with a specific query string value removed.
Definition: Uri.php:302
$authority
static isDefaultPort(UriInterface $uri)
Whether the URI has the default port of the current scheme.
Definition: Uri.php:150
$key
Definition: croninfo.php:18
getQuery()
Retrieve the query string of the URI.
getFragment()
Retrieve the fragment component of the URI.
Definition: Uri.php:422
getPath()
Retrieve the path component of the URI.
Definition: Uri.php:412
static $charSubDelims
Definition: Uri.php:38