src/Routing/I18nRouter.php line 121

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Routing;
  4. use App\Locale\LocaleProviderInterface;
  5. use App\Locale\LocaleResolver;
  6. use BestIt\Routing\Router\AbstractRouter;
  7. use Symfony\Component\Routing\Exception\ResourceNotFoundException;
  8. use Symfony\Component\Routing\Exception\RouteNotFoundException;
  9. use Symfony\Component\Routing\Generator\UrlGenerator;
  10. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  11. use Symfony\Component\Routing\RouteCollection;
  12. use Symfony\Component\Routing\RouterInterface;
  13. /**
  14. * Class I18nRouter
  15. *
  16. * @author André Varelmann <andre.varelmann@bestit-online.de>
  17. * @package App\Routing
  18. */
  19. class I18nRouter extends AbstractRouter
  20. {
  21. private RouterInterface $defaultRouter;
  22. private I18nLoader $i18nLoader;
  23. private LocaleResolver $localeResolver;
  24. private LocaleProviderInterface $localeProvider;
  25. private ?RouteCollection $routeCollection = null;
  26. private ?UrlGeneratorInterface $generator = null;
  27. /**
  28. * I18nRouter constructor.
  29. *
  30. * @param RouterInterface $defaultRouter
  31. * @param I18nLoader $i18nLoader
  32. * @param LocaleResolver $localeResolver
  33. * @param LocaleProviderInterface $localeProvider
  34. */
  35. public function __construct(
  36. RouterInterface $defaultRouter,
  37. I18nLoader $i18nLoader,
  38. LocaleResolver $localeResolver,
  39. LocaleProviderInterface $localeProvider
  40. ) {
  41. $this->defaultRouter = $defaultRouter;
  42. $this->localeResolver = $localeResolver;
  43. $this->i18nLoader = $i18nLoader;
  44. $this->localeProvider = $localeProvider;
  45. }
  46. /**
  47. * @return RouteCollection
  48. */
  49. public function getRouteCollection(): RouteCollection
  50. {
  51. if (!$this->routeCollection) {
  52. $this->routeCollection = $this->i18nLoader->load($this->defaultRouter->getRouteCollection());
  53. }
  54. return $this->routeCollection;
  55. }
  56. public function getGenerator(): UrlGeneratorInterface
  57. {
  58. if (null === $this->generator) {
  59. $this->generator = new UrlGenerator(
  60. $this->getRouteCollection(),
  61. $this->defaultRouter->getContext(),
  62. null,
  63. $this->localeProvider->getLocaleInfo()->getDefaultLocale()
  64. );
  65. }
  66. return $this->generator;
  67. }
  68. /**
  69. * Generates a URL or path for a specific route based on the given parameters.
  70. *
  71. * @throws RouteNotFoundException
  72. *
  73. * @param string $name
  74. * @param array $parameters
  75. * @param int $referenceType
  76. *
  77. * @return string
  78. */
  79. public function generate(string $name, array $parameters = [], int $referenceType = self::ABSOLUTE_PATH): string
  80. {
  81. $localeInfo = $this->localeProvider->getLocaleInfo();
  82. $currentLocaleCode = $localeInfo->getLocaleCode($localeInfo->getCurrentLocale());
  83. $i18nName = sprintf('%s.%s', $name, $currentLocaleCode);
  84. $i18nRoute = $this->getRouteCollection()->get($i18nName);
  85. if (!$i18nRoute) {
  86. throw new RouteNotFoundException('Translated route not found');
  87. }
  88. $parameters = array_merge($parameters, ['_locale' => $currentLocaleCode]);
  89. return $this->getGenerator()->generate($name, $parameters, $referenceType);
  90. }
  91. /**
  92. * Tries to match a URL path with a set of routes.
  93. *
  94. * @param string $path
  95. *
  96. * @throws RouteNotFoundException
  97. *
  98. * @return array
  99. */
  100. public function match(string $path): array
  101. {
  102. $result = null;
  103. $localeInfo = $this->localeResolver->resolveFromPath($path);
  104. $locale = $localeInfo->getCurrentLocale();
  105. $trimPath = rtrim($path, '\//');
  106. foreach ($this->getRouteCollection() as $route) {
  107. if (rtrim($route->getPath(), '\//') === $trimPath) {
  108. $result = array_merge(
  109. $this->defaultRouter->match($route->getDefault('_org_path')),
  110. ['_locale' => $locale]
  111. );
  112. break;
  113. }
  114. }
  115. // for dynamic routes try path without the locale prefix on the default router
  116. if ($result === null && strpos($path, sprintf('/%s/', $localeInfo->getLocaleCode($locale))) === 0) {
  117. $result = array_merge(
  118. $this->defaultRouter->match(substr($path, 3)),
  119. ['_locale' => $locale]
  120. );
  121. }
  122. if (!$result) {
  123. throw new ResourceNotFoundException('No redirect required.');
  124. }
  125. return $result;
  126. }
  127. }