diff --git a/src/SlmLocale/Strategy/UriPathStrategy.php b/src/SlmLocale/Strategy/UriPathStrategy.php index bb1c793..9d383d5 100644 --- a/src/SlmLocale/Strategy/UriPathStrategy.php +++ b/src/SlmLocale/Strategy/UriPathStrategy.php @@ -44,7 +44,7 @@ use SlmLocale\LocaleEvent; use Zend\ServiceManager\ServiceLocatorInterface; use Zend\ServiceManager\ServiceLocatorAwareInterface; -use Zend\Stdlib\RequestInterface; +use Zend\Uri\Uri; use Zend\Mvc\Router\Http\TreeRouteStack; class UriPathStrategy extends AbstractStrategy implements ServiceLocatorAwareInterface @@ -112,13 +112,8 @@ public function detect(LocaleEvent $event) return; } - $base = null; - $router = $this->getRouter(); - if ($router instanceof TreeRouteStack) { - $base = $router->getBaseUrl(); - } - - $locale = $this->getFirstSegmentInPath($request, $base); + $base = $this->getBasePath(); + $locale = $this->getFirstSegmentInPath($request->getUri(), $base); if (!$locale) { return; } @@ -154,15 +149,11 @@ public function found(LocaleEvent $event) } } - $base = null; - $router = $this->getRouter(); - if ($router instanceof TreeRouteStack) { - $base = $router->getBaseUrl(); - } - $router->setBaseUrl($base . '/' . $locale); + $base = $this->getBasePath(); + $found = $this->getFirstSegmentInPath($request->getUri(), $base); - $found = $this->getFirstSegmentInPath($request, $base); + $this->getRouter()->setBaseUrl($base . '/' . $locale); if ($locale === $found) { return; } @@ -191,20 +182,43 @@ public function found(LocaleEvent $event) public function assemble(LocaleEvent $event) { - $current = Locale::getDefault(); - $locale = $event->getLocale(); $uri = $event->getUri(); - $path = $uri->getPath(); + $base = $this->getBasePath(); + $locale = $event->getLocale(); + + $current = $this->getFirstSegmentInPath($uri, $base); + + if (!$this->redirectToCanonical() && null !== $this->getAliases()) { + $alias = $this->getAliasForLocale($locale); + if (null !== $alias) { + $locale = $alias; + } + } + + $path = $uri->getPath(); + + // Last part of base is now always locale, remove that + $parts = explode('/', trim($base, '/')); + array_pop($parts); + $base = implode('/', $parts); + + if ($base) { + $path = substr($path, strlen($base)); + } + $parts = explode('/', trim($path, '/')); + + // Remove first part + array_shift($parts); - $path = str_replace($current, $locale, $path); + $path = $base . '/' . $locale . '/' . implode('/', $parts); $uri->setPath($path); return $uri; } - protected function getFirstSegmentInPath(RequestInterface $request, $base = null) + protected function getFirstSegmentInPath(Uri $uri, $base = null) { - $path = $request->getUri()->getPath(); + $path = $uri->getPath(); if ($base) { $path = substr($path, strlen($base)); @@ -224,4 +238,15 @@ protected function getAliasForLocale($locale) } } } + + protected function getBasePath() + { + $base = null; + $router = $this->getRouter(); + if ($router instanceof TreeRouteStack) { + $base = $router->getBaseUrl(); + } + + return $base; + } } diff --git a/tests/SlmLocaleTest/Strategy/UriPathStrategyTest.php b/tests/SlmLocaleTest/Strategy/UriPathStrategyTest.php index c9495cb..1a6bfc3 100644 --- a/tests/SlmLocaleTest/Strategy/UriPathStrategyTest.php +++ b/tests/SlmLocaleTest/Strategy/UriPathStrategyTest.php @@ -49,6 +49,7 @@ use Zend\Mvc\Router\Http\TreeRouteStack as HttpRouter; use Zend\Mvc\Router\Console\SimpleRouteStack as ConsoleRouter; use Zend\ServiceManager\ServiceManager; +use Zend\Uri\Uri; class UriPathStrategyTest extends TestCase { @@ -277,6 +278,77 @@ public function testFoundDoesNotRedirectWhenLocaleIsInPath() $this->assertFalse($header); } + public function testAssembleReplacesLocaleInPath() + { + $uri = new Uri('/en-US/'); + + $this->event->setLocale('en-GB'); + $this->event->setUri($uri); + + $this->strategy->assemble($this->event); + + $expected = '/en-GB/'; + $actual = $this->event->getUri()->getPath(); + + $this->assertEquals($expected, $actual); + } + + public function testAssembleReplacesLocaleInDeepPath() + { + $uri = new Uri('/en-US/foo/bar/baz'); + + $this->event->setLocale('en-GB'); + $this->event->setUri($uri); + + $this->strategy->assemble($this->event); + + $expected = '/en-GB/foo/bar/baz'; + $actual = $this->event->getUri()->getPath(); + + $this->assertEquals($expected, $actual); + } + + /** + * @todo Is this a bug in the strategy? + */ + // public function testAssembleRespectsRouterBasePath() + // { + // $manager = $this->getPluginManager(); + // $router = $manager->getServiceLocator()->get('router'); + // $router->setBaseUrl('/some/deep/installation/path'); + // $this->strategy->setServiceLocator($manager); + + // $uri = new Uri('/some/deep/installation/path/en-US/foo/bar/baz'); + + // $this->event->setLocale('en-GB'); + // $this->event->setUri($uri); + + // $this->strategy->assemble($this->event); + + // $expected = 'some/deep/installation/path/en-GB/foo/bar/baz'; + // $actual = $this->event->getUri()->getPath(); + + // $this->assertEquals($expected, $actual); + // } + + public function testAssembleWorksWithAliasesToo() + { + $uri = new Uri('/nl/foo/bar/baz'); + + $this->event->setLocale('en-US'); + $this->event->setUri($uri); + + $this->strategy->setOptions(array( + 'aliases' => array('nl' => 'nl-NL', 'en' => 'en-US'), + )); + $this->strategy->assemble($this->event); + + $expected = '/en/foo/bar/baz'; + $actual = $this->event->getUri()->getPath(); + + $this->assertEquals($expected, $actual); + } + protected function getPluginManager($console = false) { $sl = new ServiceManager;