UriFactory.php 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. <?php
  2. /**
  3. * @package Grav\Framework\Uri
  4. *
  5. * @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
  6. * @license MIT License; see LICENSE file for details.
  7. */
  8. namespace Grav\Framework\Uri;
  9. /**
  10. * Class Uri
  11. * @package Grav\Framework\Uri
  12. */
  13. class UriFactory
  14. {
  15. /**
  16. * @param array $env
  17. * @return Uri
  18. * @throws \InvalidArgumentException
  19. */
  20. public static function createFromEnvironment(array $env)
  21. {
  22. return new Uri(static::parseUrlFromEnvironment($env));
  23. }
  24. /**
  25. * @param string $uri
  26. * @return Uri
  27. * @throws \InvalidArgumentException
  28. */
  29. public static function createFromString($uri)
  30. {
  31. return new Uri(static::parseUrl($uri));
  32. }
  33. /**
  34. * Creates a URI from a array of `parse_url()` components.
  35. *
  36. * @param array $parts
  37. * @return Uri
  38. * @throws \InvalidArgumentException
  39. */
  40. public static function createFromParts(array $parts)
  41. {
  42. return new Uri($parts);
  43. }
  44. /**
  45. * @param array $env
  46. * @return array
  47. * @throws \InvalidArgumentException
  48. */
  49. public static function parseUrlFromEnvironment(array $env)
  50. {
  51. // Build scheme.
  52. if (isset($env['REQUEST_SCHEME'])) {
  53. $scheme = strtolower($env['REQUEST_SCHEME']);
  54. } else {
  55. $https = $env['HTTPS'] ?? '';
  56. $scheme = (empty($https) || strtolower($https) === 'off') ? 'http' : 'https';
  57. }
  58. // Build user and password.
  59. $user = $env['PHP_AUTH_USER'] ?? '';
  60. $pass = $env['PHP_AUTH_PW'] ?? '';
  61. // Build host.
  62. $host = 'localhost';
  63. if (isset($env['HTTP_HOST'])) {
  64. $host = $env['HTTP_HOST'];
  65. } elseif (isset($env['SERVER_NAME'])) {
  66. $host = $env['SERVER_NAME'];
  67. }
  68. // Remove port from HTTP_HOST generated $hostname
  69. $host = explode(':', $host)[0];
  70. // Build port.
  71. $port = isset($env['SERVER_PORT']) ? (int)$env['SERVER_PORT'] : null;
  72. // Build path.
  73. $request_uri = $env['REQUEST_URI'] ?? '';
  74. $path = parse_url('http://example.com' . $request_uri, PHP_URL_PATH);
  75. // Build query string.
  76. $query = $env['QUERY_STRING'] ?? '';
  77. if ($query === '') {
  78. $query = parse_url('http://example.com' . $request_uri, PHP_URL_QUERY);
  79. }
  80. // Support ngnix routes.
  81. if (strpos($query, '_url=') === 0) {
  82. parse_str($query, $q);
  83. unset($q['_url']);
  84. $query = http_build_query($q);
  85. }
  86. return [
  87. 'scheme' => $scheme,
  88. 'user' => $user,
  89. 'pass' => $pass,
  90. 'host' => $host,
  91. 'port' => $port,
  92. 'path' => $path,
  93. 'query' => $query
  94. ];
  95. }
  96. /**
  97. * UTF-8 aware parse_url() implementation.
  98. *
  99. * @param string $url
  100. * @return array
  101. * @throws \InvalidArgumentException
  102. */
  103. public static function parseUrl($url)
  104. {
  105. if (!\is_string($url)) {
  106. throw new \InvalidArgumentException('URL must be a string');
  107. }
  108. $encodedUrl = preg_replace_callback(
  109. '%[^:/@?&=#]+%u',
  110. function ($matches) { return rawurlencode($matches[0]); },
  111. $url
  112. );
  113. $parts = \is_string($encodedUrl) ? parse_url($encodedUrl) : false;
  114. if ($parts === false) {
  115. throw new \InvalidArgumentException("Malformed URL: {$url}");
  116. }
  117. return $parts;
  118. }
  119. /**
  120. * Parse query string and return it as an array.
  121. *
  122. * @param string $query
  123. * @return mixed
  124. */
  125. public static function parseQuery($query)
  126. {
  127. parse_str($query, $params);
  128. return $params;
  129. }
  130. /**
  131. * Build query string from variables.
  132. *
  133. * @param array $params
  134. * @return string
  135. */
  136. public static function buildQuery(array $params)
  137. {
  138. if (!$params) {
  139. return '';
  140. }
  141. $separator = ini_get('arg_separator.output') ?: '&';
  142. return http_build_query($params, '', $separator, PHP_QUERY_RFC3986);
  143. }
  144. }