Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions DependencyInjection/Compiler/RegisterRouteEnhancersPass.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,23 @@ class RegisterRouteEnhancersPass implements CompilerPassInterface
/**
* @var string
*/
protected $dynamicRouterService;
protected $conditionalEnhancer;

protected $enhancerTag;

public function __construct($dynamicRouterService = 'cmf_routing.dynamic_router', $enhancerTag = 'dynamic_router_route_enhancer')
public function __construct($conditionalEnhancer = 'cmf_routing.conditional_enhancer', $enhancerTag = 'dynamic_router_route_enhancer')
{
$this->dynamicRouterService = $dynamicRouterService;
$this->conditionalEnhancer = $conditionalEnhancer;
$this->enhancerTag = $enhancerTag;
}

public function process(ContainerBuilder $container)
{
if (!$container->hasDefinition($this->dynamicRouterService)) {
if (!$container->hasDefinition($this->conditionalEnhancer)) {
return;
}

$router = $container->getDefinition($this->dynamicRouterService);
$router = $container->getDefinition($this->conditionalEnhancer);

foreach ($container->findTaggedServiceIds($this->enhancerTag) as $id => $attributes) {
$priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0;
Expand Down
109 changes: 17 additions & 92 deletions DynamicRouter.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,18 +53,6 @@ class DynamicRouter implements RouterInterface, RequestMatcherInterface, Chained
*/
protected $eventDispatcher;

/**
* @var RouteEnhancerInterface[]
*/
protected $enhancers = array();

/**
* Cached sorted list of enhancers.
*
* @var RouteEnhancerInterface[]
*/
protected $sortedEnhancers = array();

/**
* The regexp pattern that needs to be matched before a dynamic lookup is
* made.
Expand All @@ -83,20 +71,28 @@ class DynamicRouter implements RouterInterface, RequestMatcherInterface, Chained
*/
private $routeCollection;

/**
* @var RouteEnhancerInterface
*/
private $enhancer;

/**
* @param RequestContext $context
* @param RequestMatcherInterface|UrlMatcherInterface $matcher
* @param UrlGeneratorInterface $generator
* @param RouteEnhancerInterface $enhancer
* @param string $uriFilterRegexp
* @param EventDispatcherInterface|null $eventDispatcher
* @param RouteProviderInterface $provider
*/
public function __construct(RequestContext $context,
$matcher,
UrlGeneratorInterface $generator,
$uriFilterRegexp = '',
EventDispatcherInterface $eventDispatcher = null,
RouteProviderInterface $provider = null
public function __construct(
RequestContext $context,
$matcher,
UrlGeneratorInterface $generator,
RouteEnhancerInterface $enhancer,
$uriFilterRegexp = '',
EventDispatcherInterface $eventDispatcher = null,
RouteProviderInterface $provider = null
) {
$this->context = $context;
if (!$matcher instanceof RequestMatcherInterface && !$matcher instanceof UrlMatcherInterface) {
Expand All @@ -109,6 +105,7 @@ public function __construct(RequestContext $context,
$this->provider = $provider;

$this->generator->setContext($context);
$this->enhancer = $enhancer;
}

/**
Expand Down Expand Up @@ -234,7 +231,7 @@ public function match($pathinfo)

$defaults = $matcher->match($pathinfo);

return $this->applyRouteEnhancers($defaults, $request);
return $this->enhancer->enhance($defaults, $request);
}

/**
Expand Down Expand Up @@ -272,79 +269,7 @@ public function matchRequest(Request $request)
$defaults = $matcher->matchRequest($request);
}

return $this->applyRouteEnhancers($defaults, $request);
}

/**
* Apply the route enhancers to the defaults, according to priorities.
*
* @param array $defaults
* @param Request $request
*
* @return array
*/
protected function applyRouteEnhancers($defaults, Request $request)
{
foreach ($this->getRouteEnhancers() as $enhancer) {
$defaults = $enhancer->enhance($defaults, $request);
}

return $defaults;
}

/**
* Add route enhancers to the router to let them generate information on
* matched routes.
*
* The order of the enhancers is determined by the priority, the higher the
* value, the earlier the enhancer is run.
*
* @param RouteEnhancerInterface $enhancer
* @param int $priority
*/
public function addRouteEnhancer(RouteEnhancerInterface $enhancer, $priority = 0)
{
if (empty($this->enhancers[$priority])) {
$this->enhancers[$priority] = array();
}

$this->enhancers[$priority][] = $enhancer;
$this->sortedEnhancers = array();

return $this;
}

/**
* Sorts the enhancers and flattens them.
*
* @return RouteEnhancerInterface[] the enhancers ordered by priority
*/
public function getRouteEnhancers()
{
if (empty($this->sortedEnhancers)) {
$this->sortedEnhancers = $this->sortRouteEnhancers();
}

return $this->sortedEnhancers;
}

/**
* Sort enhancers by priority.
*
* The highest priority number is the highest priority (reverse sorting).
*
* @return RouteEnhancerInterface[] the sorted enhancers
*/
protected function sortRouteEnhancers()
{
$sortedEnhancers = array();
krsort($this->enhancers);

foreach ($this->enhancers as $enhancers) {
$sortedEnhancers = array_merge($sortedEnhancers, $enhancers);
}

return $sortedEnhancers;
return $this->enhancer->enhance($defaults, $request);
}

/**
Expand Down
170 changes: 170 additions & 0 deletions Enhancer/ConditionalEnhancer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
<?php

namespace Symfony\Cmf\Component\Routing\Enhancer;

use Symfony\Component\HttpFoundation\Request;

/**
* @author Maximilian Berghoff <Maximilian.Berghoff@mayflower.de>
*/
class ConditionalEnhancer implements RouteEnhancerInterface
{
/**
* @var RouteEnhancerInterface[][]
*/
protected $enhancers = array();

/**
* Cached sorted list of enhancers.
*
* @var RouteEnhancerInterface[]
*/
protected $sortedEnhancers = array();

/**
* The complete and available mapping separated by its name as the key.
*
* @var array
*/
private $mapping;

/**
* @var Request
*/
private $request;

/**
* Key that can should be used in a http method aware defaults configuration.
*/
const KEY_METHODS = 'methods';
const KEY_VALUE = 'value';

/**
* Matches all http methods.
*/
const METHOD_ANY = 'any';

public function __construct(array $mapping)
{
$this->mapping = $mapping;
}

/**
* {@inheritdoc}
*/
public function enhance(array $defaults, Request $request)
{
$this->request = $request;
foreach ($this->getRouteEnhancers() as $enhancer) {
$defaults = $enhancer->enhance($defaults, $this->request);
}

return $defaults;
}

/**
* Add route enhancers to the router to let them generate information on
* matched routes.
*
* The order of the enhancers is determined by the priority, the higher the
* value, the earlier the enhancer is run.
*
* @param RouteEnhancerInterface $enhancer
* @param int $priority
*
* @return $this
*/
public function addRouteEnhancer(RouteEnhancerInterface $enhancer, $priority = 0)
{
if (empty($this->enhancers[$priority])) {
$this->enhancers[$priority] = array();
}

$this->enhancers[$priority][] = $enhancer;
$this->sortedEnhancers = array();

return $this;
}

/**
* Sorts the enhancers and flattens them.
*
* @return RouteEnhancerInterface[] the enhancers ordered by priority
*/
public function getRouteEnhancers()
{
if (empty($this->sortedEnhancers)) {
$this->sortedEnhancers = $this->sortAndWarmEnhancers();
}

return $this->sortedEnhancers;
}

/**
* Sort enhancers by priority.
*
* The highest priority number is the highest priority (reverse sorting).
*
* @return RouteEnhancerInterface[] the sorted enhancers
*/
protected function sortAndWarmEnhancers()
{
$sortedEnhancers = array();
krsort($this->enhancers);

$mapping = $this->mapping;
$request = $this->request;
foreach ($this->enhancers as $enhancers) {
$map = array_map(
function (RouteEnhancerInterface $enhancer) use ($mapping, $request) {
foreach ($mapping as $name => $map) {
if ($enhancer instanceof WithMapping && $enhancer->isName($name)) {
$enhancer->setMapping(ConditionalEnhancer::transformMethodAwareMapping($map, $request));

return $enhancer;
}
}

return $enhancer instanceof WithMapping ? null : $enhancer;
},
$enhancers
);
$sortedEnhancers = array_merge($sortedEnhancers, array_filter($map, function ($enhancer) {
return null !== $enhancer;
}));
}
foreach ($this->mapping as $name => $mapping) {

}

return $sortedEnhancers;
}

/**
* {@inheritdoc}
*/
public function isName($name)
{
return false;
}

public static function transformMethodAwareMapping($mappings, Request $request)
{
$transformed = array();
foreach ($mappings as $mapping) {
if (!is_array($mapping) || !isset($mapping[self::KEY_METHODS])|| !isset($mapping[self::KEY_VALUE])) {
$transformed[] = $mapping;
continue;
}

if (is_array($mapping[self::KEY_METHODS])
&& (in_array(strtolower($request->getMethod()), $mapping[self::KEY_METHODS])
|| in_array(self::METHOD_ANY, $mapping[self::KEY_METHODS]))
) {
$transformed[] = $mapping[self::KEY_VALUE];
}
}

return $transformed;
}
}
Loading