UrlHelper.php 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\HttpFoundation;
  11. use Symfony\Component\Routing\RequestContext;
  12. use Symfony\Component\Routing\RequestContextAwareInterface;
  13. /**
  14. * A helper service for manipulating URLs within and outside the request scope.
  15. *
  16. * @author Valentin Udaltsov <udaltsov.valentin@gmail.com>
  17. */
  18. final class UrlHelper
  19. {
  20. private $requestStack;
  21. private $requestContext;
  22. /**
  23. * @param RequestContextAwareInterface|RequestContext|null $requestContext
  24. */
  25. public function __construct(RequestStack $requestStack, $requestContext = null)
  26. {
  27. if (null !== $requestContext && !$requestContext instanceof RequestContext && !$requestContext instanceof RequestContextAwareInterface) {
  28. throw new \TypeError(__METHOD__.': Argument #2 ($requestContext) must of type Symfony\Component\Routing\RequestContextAwareInterface|Symfony\Component\Routing\RequestContext|null, '.get_debug_type($requestContext).' given.');
  29. }
  30. $this->requestStack = $requestStack;
  31. $this->requestContext = $requestContext;
  32. }
  33. public function getAbsoluteUrl(string $path): string
  34. {
  35. if (str_contains($path, '://') || '//' === substr($path, 0, 2)) {
  36. return $path;
  37. }
  38. if (null === $request = $this->requestStack->getMainRequest()) {
  39. return $this->getAbsoluteUrlFromContext($path);
  40. }
  41. if ('#' === $path[0]) {
  42. $path = $request->getRequestUri().$path;
  43. } elseif ('?' === $path[0]) {
  44. $path = $request->getPathInfo().$path;
  45. }
  46. if (!$path || '/' !== $path[0]) {
  47. $prefix = $request->getPathInfo();
  48. $last = \strlen($prefix) - 1;
  49. if ($last !== $pos = strrpos($prefix, '/')) {
  50. $prefix = substr($prefix, 0, $pos).'/';
  51. }
  52. return $request->getUriForPath($prefix.$path);
  53. }
  54. return $request->getSchemeAndHttpHost().$path;
  55. }
  56. public function getRelativePath(string $path): string
  57. {
  58. if (str_contains($path, '://') || '//' === substr($path, 0, 2)) {
  59. return $path;
  60. }
  61. if (null === $request = $this->requestStack->getMainRequest()) {
  62. return $path;
  63. }
  64. return $request->getRelativeUriForPath($path);
  65. }
  66. private function getAbsoluteUrlFromContext(string $path): string
  67. {
  68. if (null === $context = $this->requestContext) {
  69. return $path;
  70. }
  71. if ($context instanceof RequestContextAwareInterface) {
  72. $context = $context->getContext();
  73. }
  74. if ('' === $host = $context->getHost()) {
  75. return $path;
  76. }
  77. $scheme = $context->getScheme();
  78. $port = '';
  79. if ('http' === $scheme && 80 !== $context->getHttpPort()) {
  80. $port = ':'.$context->getHttpPort();
  81. } elseif ('https' === $scheme && 443 !== $context->getHttpsPort()) {
  82. $port = ':'.$context->getHttpsPort();
  83. }
  84. if ('#' === $path[0]) {
  85. $queryString = $context->getQueryString();
  86. $path = $context->getPathInfo().($queryString ? '?'.$queryString : '').$path;
  87. } elseif ('?' === $path[0]) {
  88. $path = $context->getPathInfo().$path;
  89. }
  90. if ('/' !== $path[0]) {
  91. $path = rtrim($context->getBaseUrl(), '/').'/'.$path;
  92. }
  93. return $scheme.'://'.$host.$port.$path;
  94. }
  95. }