Skip to content

Commit

Permalink
add redirect to locale-prefix for partial match requests
Browse files Browse the repository at this point in the history
  • Loading branch information
wachterjohannes committed Aug 9, 2019
1 parent 718040b commit 288d51d
Show file tree
Hide file tree
Showing 4 changed files with 301 additions and 36 deletions.
29 changes: 29 additions & 0 deletions UPGRADE.md
@@ -1,5 +1,34 @@
# Upgrade

## dev-release/1.5

### RouteProvider

The method `Sulu\Bundle\RouteBundle\Routing\RouteProvider::__construct` has removed the second parameter.

__Before:__

```
public function __construct(
RouteRepositoryInterface $routeRepository,
RequestAnalyzerInterface $requestAnalyzer,
RouteDefaultsProviderInterface $routeDefaultsProvider,
RequestStack $requestStack,
LazyLoadingValueHolderFactory $proxyFactory = null
)
```

__After:__

```
public function __construct(
RouteRepositoryInterface $routeRepository,
RouteDefaultsProviderInterface $routeDefaultsProvider,
RequestStack $requestStack,
LazyLoadingValueHolderFactory $proxyFactory = null
)
```

## 1.5.21

### User API performance improvement
Expand Down
1 change: 0 additions & 1 deletion src/Sulu/Bundle/RouteBundle/Resources/config/routing.xml
Expand Up @@ -26,7 +26,6 @@

<service id="sulu_route.routing.provider" class="Sulu\Bundle\RouteBundle\Routing\RouteProvider">
<argument type="service" id="sulu.repository.route"/>
<argument type="service" id="sulu_core.webspace.request_analyzer"/>
<argument type="service" id="sulu_route.routing.defaults_provider"/>
<argument type="service" id="request_stack"/>
<argument type="service" id="sulu_route.routing.proxy_factory"/>
Expand Down
96 changes: 72 additions & 24 deletions src/Sulu/Bundle/RouteBundle/Routing/RouteProvider.php
Expand Up @@ -18,6 +18,7 @@
use Sulu\Bundle\RouteBundle\Entity\RouteRepositoryInterface;
use Sulu\Bundle\RouteBundle\Model\RouteInterface;
use Sulu\Bundle\RouteBundle\Routing\Defaults\RouteDefaultsProviderInterface;
use Sulu\Component\Webspace\Analyzer\Attributes\RequestAttributes;
use Sulu\Component\Webspace\Analyzer\RequestAnalyzerInterface;
use Symfony\Cmf\Component\Routing\RouteProviderInterface;
use Symfony\Component\HttpFoundation\Request;
Expand All @@ -38,11 +39,6 @@ class RouteProvider implements RouteProviderInterface
*/
private $routeRepository;

/**
* @var RequestAnalyzerInterface
*/
private $requestAnalyzer;

/**
* @var RouteDefaultsProviderInterface
*/
Expand All @@ -68,22 +64,13 @@ class RouteProvider implements RouteProviderInterface
*/
private $routeCache = [];

/**
* @param RouteRepositoryInterface $routeRepository
* @param RequestAnalyzerInterface $requestAnalyzer
* @param RouteDefaultsProviderInterface $routeDefaultsProvider
* @param RequestStack $requestStack
* @param LazyLoadingValueHolderFactory $proxyFactory
*/
public function __construct(
RouteRepositoryInterface $routeRepository,
RequestAnalyzerInterface $requestAnalyzer,
RouteDefaultsProviderInterface $routeDefaultsProvider,
RequestStack $requestStack,
LazyLoadingValueHolderFactory $proxyFactory = null
) {
$this->routeRepository = $routeRepository;
$this->requestAnalyzer = $requestAnalyzer;
$this->routeDefaultsProvider = $routeDefaultsProvider;
$this->requestStack = $requestStack;

Expand All @@ -96,13 +83,34 @@ public function __construct(
public function getRouteCollectionForRequest(Request $request)
{
$collection = new RouteCollection();
$path = $request->getPathInfo();
$prefix = $this->requestAnalyzer->getResourceLocatorPrefix();
$path = $this->decodePathInfo($request->getPathInfo());

/** @var RequestAttributes|null $attributes */
$attributes = $request->attributes->get('_sulu');
if (!$attributes) {
return $collection;
}

$matchType = $attributes->getAttribute('matchType');
if (RequestAnalyzerInterface::MATCH_TYPE_REDIRECT == $matchType
|| RequestAnalyzerInterface::MATCH_TYPE_PARTIAL == $matchType
) {
return $collection;
}

$prefix = $attributes->getAttribute('resourceLocatorPrefix');

if (!empty($prefix) && 0 === strpos($path, $prefix)) {
$path = PathHelper::relativizePath($path, $prefix);
}

// when the URI ends with a dot - symfony returns empty request-format
if ('' === $format = $request->getRequestFormat()) {
return $collection;
}

$path = $this->stripFormatExtension($path, $format);

$route = $this->findRouteByPath($path, $request->getLocale());
if ($route && array_key_exists($route->getId(), $this->symfonyRouteCache)) {
$collection->add(
Expand All @@ -124,10 +132,7 @@ public function getRouteCollectionForRequest(Request $request)
return $collection;
}

$collection->add(
self::ROUTE_PREFIX . $route->getId(),
$this->createRoute($route, $request)
);
$collection->add(self::ROUTE_PREFIX . $route->getId(), $this->createRoute($route, $request, $attributes));

return $collection;
}
Expand Down Expand Up @@ -159,6 +164,14 @@ public function getRouteByName($name)
throw new RouteNotFoundException();
}

$request = $this->requestStack->getCurrentRequest();

/** @var RequestAttributes $attributes */
$attributes = $request->attributes->get('_sulu');
if (!$attributes) {
throw new RouteNotFoundException();
}

$routeId = substr($name, strlen(self::ROUTE_PREFIX));
if (array_key_exists($routeId, $this->symfonyRouteCache)) {
return $this->symfonyRouteCache[$routeId];
Expand All @@ -178,7 +191,7 @@ public function getRouteByName($name)
throw new RouteNotFoundException();
}

return $this->createRoute($route, $this->requestStack->getCurrentRequest());
return $this->createRoute($route, $request, $attributes);
}

/**
Expand All @@ -197,17 +210,17 @@ public function getRoutesByNames($names)
*
* @return Route
*/
protected function createRoute(RouteInterface $route, Request $request)
protected function createRoute(RouteInterface $route, Request $request, RequestAttributes $attributes)
{
$routePath = $this->requestAnalyzer->getResourceLocatorPrefix() . $route->getPath();
$routePath = $this->decodePathInfo($request->getPathInfo());

if ($route->isHistory()) {
return new Route(
$routePath,
[
'_controller' => 'SuluWebsiteBundle:Redirect:redirect',
'url' => $request->getSchemeAndHttpHost()
. $this->requestAnalyzer->getResourceLocatorPrefix()
. $attributes->getAttribute('resourceLocatorPrefix')
. $route->getTarget()->getPath()
. ($request->getQueryString() ? ('?' . $request->getQueryString()) : ''),
]
Expand Down Expand Up @@ -237,4 +250,39 @@ function(&$wrappedObject, LazyLoadingInterface $proxy, $method, array $parameter

return $this->symfonyRouteCache[$route->getId()] = $symfonyRoute;
}

/**
* Server encodes the url and symfony does not encode it
* Symfony decodes this data here https://github.com/symfony/symfony/blob/3.3/src/Symfony/Component/Routing/Matcher/UrlMatcher.php#L91.
*
* @param $pathInfo
*
* @return string
*/
private function decodePathInfo($pathInfo)
{
if (null === $pathInfo || '' === $pathInfo) {
return '';
}

return '/' . ltrim(rawurldecode($pathInfo), '/');
}

/**
* Return the given path without the format extension.
*
* @param string $path
* @param string $format
*
* @return string
*/
private function stripFormatExtension($path, $format)
{
$extension = '.' . $format;
if (substr($path, -strlen($extension)) === $extension) {
$path = substr($path, 0, strlen($path) - strlen($extension));
}

return $path;
}
}

0 comments on commit 288d51d

Please sign in to comment.