Url.php 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * The Minz_Url class handles URLs across the MINZ framework
  5. */
  6. class Minz_Url {
  7. /**
  8. * Display a formatted URL
  9. * @param string|array<string,string|array<string,mixed>> $url The URL to format, defined as an array:
  10. * $url['c'] = controller
  11. * $url['a'] = action
  12. * $url['params'] = array of additional parameters
  13. * or as a string
  14. * @param string $encoding how to encode & (& ou &amp; pour html)
  15. * @param bool|string $absolute
  16. * @return string Formatted URL
  17. */
  18. public static function display($url = [], string $encoding = 'html', $absolute = false): string {
  19. $isArray = is_array($url);
  20. if ($isArray) {
  21. $url = self::checkControllerUrl($url);
  22. }
  23. $url_string = '';
  24. if ($absolute) {
  25. $url_string = Minz_Request::getBaseUrl();
  26. if (strlen($url_string) < strlen('http://a.bc')) {
  27. $url_string = Minz_Request::guessBaseUrl();
  28. if (PUBLIC_RELATIVE === '..' && preg_match('%' . PUBLIC_TO_INDEX_PATH . '(/|$)%', $url_string)) {
  29. //TODO: Implement proper resolver of relative parts such as /test/./../
  30. $url_string = dirname($url_string);
  31. }
  32. }
  33. if ($isArray) {
  34. $url_string .= PUBLIC_TO_INDEX_PATH;
  35. }
  36. if ($absolute === 'root') {
  37. $url_string = parse_url($url_string, PHP_URL_PATH);
  38. }
  39. } else {
  40. $url_string = $isArray ? '.' : PUBLIC_RELATIVE;
  41. }
  42. if ($isArray) {
  43. $url_string .= '/' . self::printUri($url, $encoding);
  44. } elseif ($encoding === 'html') {
  45. $url_string = Minz_Helper::htmlspecialchars_utf8($url_string . $url);
  46. } else {
  47. $url_string .= $url;
  48. }
  49. return $url_string;
  50. }
  51. /**
  52. * Construit l'URI d'une URL
  53. * @param array<string,mixed> $url l'url sous forme de tableau
  54. * @param string $encodage pour indiquer comment encoder les & (& ou &amp; pour html)
  55. * @return string uri sous la forme ?key=value&key2=value2
  56. */
  57. private static function printUri(array $url, string $encodage): string {
  58. $uri = '';
  59. $separator = '?';
  60. $anchor = '';
  61. if ($encodage === 'html') {
  62. $and = '&amp;';
  63. } else {
  64. $and = '&';
  65. }
  66. if (!empty($url['params']['#'])) {
  67. $anchor = '#' . ($encodage === 'html' ? htmlspecialchars($url['params']['#'], ENT_QUOTES, 'UTF-8') : $url['params']['#']);
  68. unset($url['params']['#']);
  69. }
  70. if (isset($url['c'])
  71. && $url['c'] != Minz_Request::defaultControllerName()) {
  72. $uri .= $separator . 'c=' . $url['c'];
  73. $separator = $and;
  74. }
  75. if (isset($url['a'])
  76. && $url['a'] != Minz_Request::defaultActionName()) {
  77. $uri .= $separator . 'a=' . $url['a'];
  78. $separator = $and;
  79. }
  80. if (isset($url['params'])) {
  81. unset($url['params']['c']);
  82. unset($url['params']['a']);
  83. foreach ($url['params'] as $key => $param) {
  84. if (!is_string($key) || (!is_string($param) && !is_int($param))) {
  85. continue;
  86. }
  87. $uri .= $separator . urlencode($key) . '=' . urlencode((string)$param);
  88. $separator = $and;
  89. }
  90. }
  91. if (!empty($url['#'])) {
  92. $uri .= '#' . ($encodage === 'html' ? htmlspecialchars($url['#'], ENT_QUOTES, 'UTF-8') : $url['#']);
  93. }
  94. $uri .= $anchor;
  95. return $uri;
  96. }
  97. /**
  98. * Check that all array elements representing the controller URL are OK
  99. * @param array<string,string|array<string,mixed>> $url controller URL as array
  100. * @return array{'c':string,'a':string,'params':array<string,mixed>} Verified controller URL as array
  101. */
  102. public static function checkControllerUrl(array $url): array {
  103. return [
  104. 'c' => empty($url['c']) || !is_string($url['c']) ? Minz_Request::defaultControllerName() : $url['c'],
  105. 'a' => empty($url['a']) || !is_string($url['a']) ? Minz_Request::defaultActionName() : $url['a'],
  106. 'params' => empty($url['params']) || !is_array($url['params']) ? [] : $url['params'],
  107. ];
  108. }
  109. /** @param array{'c'?:string,'a'?:string,'params'?:array<string,mixed>} $url */
  110. public static function serialize(?array $url = []): string {
  111. if (empty($url)) {
  112. return '';
  113. }
  114. try {
  115. return base64_encode(json_encode($url, JSON_THROW_ON_ERROR));
  116. } catch (\Throwable $exception) {
  117. return '';
  118. }
  119. }
  120. /**
  121. * @phpstan-return array{'c'?:string,'a'?:string,'params'?:array<string,mixed>}
  122. * @return array<string,string|array<string,string>>
  123. */
  124. public static function unserialize(string $url = ''): array {
  125. try {
  126. return json_decode(base64_decode($url, true) ?: '', true, JSON_THROW_ON_ERROR) ?? [];
  127. } catch (\Throwable $exception) {
  128. return [];
  129. }
  130. }
  131. /**
  132. * Returns an array representing the URL as passed in the address bar
  133. * @return array{'c'?:string,'a'?:string,'params'?:array<string,mixed>} URL representation
  134. */
  135. public static function build(): array {
  136. $url = [
  137. 'c' => $_GET['c'] ?? Minz_Request::defaultControllerName(),
  138. 'a' => $_GET['a'] ?? Minz_Request::defaultActionName(),
  139. 'params' => $_GET,
  140. ];
  141. // post-traitement
  142. unset($url['params']['c']);
  143. unset($url['params']['a']);
  144. return $url;
  145. }
  146. }
  147. /**
  148. * @param string $controller
  149. * @param string $action
  150. * @param string|int ...$args
  151. * @return string|false
  152. */
  153. function _url(string $controller, string $action, ...$args) {
  154. $nb_args = count($args);
  155. if ($nb_args % 2 !== 0) {
  156. return false;
  157. }
  158. $params = array ();
  159. for ($i = 0; $i < $nb_args; $i += 2) {
  160. $arg = '' . $args[$i];
  161. $params[$arg] = '' . $args[$i + 1];
  162. }
  163. return Minz_Url::display (array ('c' => $controller, 'a' => $action, 'params' => $params));
  164. }