Commit 24448e8d authored by webchick's avatar webchick

Issue #1894934 by scor, Crell: Update CMF Routing component.

parent 26fe08d8
......@@ -15,7 +15,7 @@
"doctrine/common": "2.3.*@stable",
"guzzle/http": "3.1.*@stable",
"kriswallsmith/assetic": "1.1.*@alpha",
"symfony-cmf/routing": "1.0.*@dev",
"symfony-cmf/routing": "dev-master#ea4a10",
"easyrdf/easyrdf": "dev-master"
},
"minimum-stability": "dev"
......
{
"hash": "9dba4484f19203d80a4d60c987df2e59",
"hash": "4c18d6f1c91b78555300b0036b5a8a7e",
"packages": [
{
"name": "doctrine/common",
......@@ -385,12 +385,12 @@
"source": {
"type": "git",
"url": "https://github.com/symfony-cmf/Routing",
"reference": "1.0.0-alpha3"
"reference": "ea4a10"
},
"dist": {
"type": "zip",
"url": "https://github.com/symfony-cmf/Routing/archive/1.0.0-alpha3.zip",
"reference": "1.0.0-alpha3",
"url": "https://github.com/symfony-cmf/Routing/archive/ea4a10dd971580a9a57a69397f165e25233ba667.zip",
"reference": "ea4a10",
"shasum": ""
},
"require": {
......@@ -398,7 +398,7 @@
"symfony/routing": ">=2.1,<2.3-dev",
"symfony/http-kernel": ">=2.1,<2.3-dev"
},
"time": "2012-12-16 17:52:57",
"time": "2013-01-21 20:33:16",
"type": "library",
"extra": {
"branch-alias": {
......
......@@ -7,6 +7,7 @@
namespace Drupal\Core\EventSubscriber;
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
......@@ -38,13 +39,13 @@ public function __construct(AccessManager $access_manager) {
*/
public function onKernelRequestAccessCheck(GetResponseEvent $event) {
$request = $event->getRequest();
if (!$request->attributes->has('_route')) {
if (!$request->attributes->has(RouteObjectInterface::ROUTE_OBJECT)) {
// If no Route is available it is likely a static resource and access is
// handled elsewhere.
return;
}
$this->accessManager->check($request->attributes->get('_route'));
$this->accessManager->check($request->attributes->get(RouteObjectInterface::ROUTE_OBJECT));
}
/**
......
......@@ -12,6 +12,7 @@
namespace Drupal\Core;
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\StreamedResponse;
......@@ -153,7 +154,7 @@ public function render($controller, array $options = array())
$options['attributes']['_format'] = $request->getRequestFormat();
}
$options['attributes']['_route'] = '_internal';
$options['attributes'][RouteObjectInterface::ROUTE_OBJECT] = '_internal';
$subRequest = $request->duplicate($options['query'], null, $options['attributes']);
$subRequest->setMethod('GET');
}
......
......@@ -7,6 +7,7 @@
namespace Drupal\rest;
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
use Symfony\Component\DependencyInjection\ContainerAware;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
......@@ -29,7 +30,7 @@ class RequestHandler extends ContainerAware {
* The response object.
*/
public function handle(Request $request, $id = NULL) {
$plugin = $request->attributes->get('_route')->getDefault('_plugin');
$plugin = $request->attributes->get(RouteObjectInterface::ROUTE_OBJECT)->getDefault('_plugin');
$method = strtolower($request->getMethod());
$resource = $this->container
->get('plugin.manager.rest')
......
......@@ -4,4 +4,4 @@
require_once __DIR__ . '/composer' . '/autoload_real.php';
return ComposerAutoloaderInitcb954419c7531cdb839507174df5e8bb::getLoader();
return ComposerAutoloaderInitdff5596d4902476e49b77f22ebf69e4a::getLoader();
......@@ -75,30 +75,63 @@ public function addClassMap(array $classMap)
}
/**
* Registers a set of classes
* Registers a set of classes, merging with any others previously set.
*
* @param string $prefix The classes prefix
* @param array|string $paths The location(s) of the classes
* @param string $prefix The classes prefix
* @param array|string $paths The location(s) of the classes
* @param bool $prepend Prepend the location(s)
*/
public function add($prefix, $paths)
public function add($prefix, $paths, $prepend = false)
{
if (!$prefix) {
foreach ((array) $paths as $path) {
$this->fallbackDirs[] = $path;
if ($prepend) {
$this->fallbackDirs = array_merge(
(array) $paths,
$this->fallbackDirs
);
} else {
$this->fallbackDirs = array_merge(
$this->fallbackDirs,
(array) $paths
);
}
return;
}
if (isset($this->prefixes[$prefix])) {
if (!isset($this->prefixes[$prefix])) {
$this->prefixes[$prefix] = (array) $paths;
return;
}
if ($prepend) {
$this->prefixes[$prefix] = array_merge(
(array) $paths,
$this->prefixes[$prefix]
);
} else {
$this->prefixes[$prefix] = array_merge(
$this->prefixes[$prefix],
(array) $paths
);
} else {
$this->prefixes[$prefix] = (array) $paths;
}
}
/**
* Registers a set of classes, replacing any others previously set.
*
* @param string $prefix The classes prefix
* @param array|string $paths The location(s) of the classes
*/
public function set($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirs = (array) $paths;
return;
}
$this->prefixes[$prefix] = (array) $paths;
}
/**
* Turns on searching the include path for class files.
*
......
......@@ -2,7 +2,7 @@
// autoload_real.php generated by Composer
class ComposerAutoloaderInitcb954419c7531cdb839507174df5e8bb
class ComposerAutoloaderInitdff5596d4902476e49b77f22ebf69e4a
{
private static $loader;
......@@ -19,9 +19,9 @@ public static function getLoader()
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInitcb954419c7531cdb839507174df5e8bb', 'loadClassLoader'));
spl_autoload_register(array('ComposerAutoloaderInitdff5596d4902476e49b77f22ebf69e4a', 'loadClassLoader'));
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInitcb954419c7531cdb839507174df5e8bb', 'loadClassLoader'));
spl_autoload_unregister(array('ComposerAutoloaderInitdff5596d4902476e49b77f22ebf69e4a', 'loadClassLoader'));
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
......
......@@ -228,57 +228,6 @@
"minification"
]
},
{
"name": "symfony-cmf/routing",
"version": "dev-master",
"version_normalized": "9999999-dev",
"target-dir": "Symfony/Cmf/Component/Routing",
"source": {
"type": "git",
"url": "https://github.com/symfony-cmf/Routing",
"reference": "1.0.0-alpha3"
},
"dist": {
"type": "zip",
"url": "https://github.com/symfony-cmf/Routing/archive/1.0.0-alpha3.zip",
"reference": "1.0.0-alpha3",
"shasum": ""
},
"require": {
"php": ">=5.3.2",
"symfony/routing": ">=2.1,<2.3-dev",
"symfony/http-kernel": ">=2.1,<2.3-dev"
},
"time": "2012-12-16 17:52:57",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"installation-source": "source",
"autoload": {
"psr-0": {
"Symfony\\Cmf\\Component\\Routing": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Symfony CMF Community",
"homepage": "https://github.com/symfony-cmf/Routing/contributors"
}
],
"description": "Extends the Symfony2 routing component for dynamic routes and chaining several routers",
"homepage": "http://cmf.symfony.com",
"keywords": [
"database",
"routing"
]
},
{
"name": "symfony/class-loader",
"version": "dev-master",
......@@ -980,5 +929,56 @@
"Turtle",
"Linked Data"
]
},
{
"name": "symfony-cmf/routing",
"version": "dev-master",
"version_normalized": "9999999-dev",
"target-dir": "Symfony/Cmf/Component/Routing",
"source": {
"type": "git",
"url": "https://github.com/symfony-cmf/Routing",
"reference": "ea4a10"
},
"dist": {
"type": "zip",
"url": "https://github.com/symfony-cmf/Routing/archive/ea4a10dd971580a9a57a69397f165e25233ba667.zip",
"reference": "ea4a10",
"shasum": ""
},
"require": {
"php": ">=5.3.2",
"symfony/routing": ">=2.1,<2.3-dev",
"symfony/http-kernel": ">=2.1,<2.3-dev"
},
"time": "2013-01-21 20:33:16",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"installation-source": "source",
"autoload": {
"psr-0": {
"Symfony\\Cmf\\Component\\Routing": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Symfony CMF Community",
"homepage": "https://github.com/symfony-cmf/Routing/contributors"
}
],
"description": "Extends the Symfony2 routing component for dynamic routes and chaining several routers",
"homepage": "http://cmf.symfony.com",
"keywords": [
"database",
"routing"
]
}
]
language: php
php:
- 5.3
- 5.4
env:
- SYMFONY_VERSION=2.1.*
- SYMFONY_VERSION=dev-master
......
......@@ -135,7 +135,7 @@ public function match($url)
{
$methodNotAllowed = null;
/** @var $router ChainedRouterInterface */
/** @var $router RouterInterface */
foreach ($this->all() as $router) {
try {
return $router->match($url);
......@@ -196,13 +196,13 @@ public function matchRequest(Request $request)
*/
public function generate($name, $parameters = array(), $absolute = false)
{
/** @var $router ChainedRouterInterface */
/** @var $router RouterInterface */
foreach ($this->all() as $router) {
// if $name and $router does not implement ChainedRouterInterface and $name is not a string, continue
// if $name and $router does not implement ChainedRouterInterface and $name is string but does not match a default Symfony2 route name, continue
if ($name && !$router instanceof ChainedRouterInterface) {
if (!is_string($name) || !preg_match('/^[a-z0-9A-Z_.]+$/', $name)) {
if (!is_string($name) || !preg_match(VersatileGeneratorInterface::CORE_NAME_PATTERN, $name)) {
continue;
}
}
......
......@@ -5,21 +5,9 @@
use Symfony\Component\Routing\RouterInterface;
/**
* Use this interface on custom routers that can handle non-string route
* "names".
* Interface to combine the VersatileGeneratorInterface with the RouterInterface
*/
interface ChainedRouterInterface extends RouterInterface
interface ChainedRouterInterface extends RouterInterface, VersatileGeneratorInterface
{
/**
* Whether the router supports the thing in $name to generate a route.
*
* This check does not need to look if the specific instance can be
* resolved to a route, only whether the router can generate routes from
* objects of this class.
* @param mixed $name The route name or route object
*
* @return bool
*/
public function supports($name);
// nothing new to add
}
\ No newline at end of file
......@@ -18,7 +18,7 @@
* A flexible router accepting matcher and generator through injection and
* using the RouteEnhancer concept to generate additional data on the routes.
*
* @author Crell
* @author Larry Garfield
* @author David Buchmann
*/
class DynamicRouter implements RouterInterface, RequestMatcherInterface, ChainedRouterInterface
......@@ -130,14 +130,18 @@ public function generate($name, $parameters = array(), $absolute = false)
}
/**
* Support any string as route name
* Delegate to our generator
*
* {@inheritDoc}
*/
public function supports($name)
{
// TODO: check $this->generator instanceof VersatileGeneratorInterface
return $this->generator->supports($name);
if ($this->generator instanceof VersatileGeneratorInterface) {
return $this->generator->supports($name);
}
return (!is_string($name) || !preg_match(VersatileGeneratorInterface::CORE_NAME_PATTERN, $name));
}
/**
......
......@@ -36,17 +36,19 @@ public function finalMatch(RouteCollection $collection, Request $request)
$attributes = $matcher->match($request->getPathInfo());
// cleanup route attributes
if (! isset($attributes['_route']) || ! $attributes['_route'] instanceof Route) {
$name = $attributes['_route'];
$route = $collection->get($attributes['_route']);
$attributes['_route'] = $route;
if (! isset($attributes[RouteObjectInterface::ROUTE_OBJECT])
|| ! $attributes[RouteObjectInterface::ROUTE_OBJECT] instanceof Route
) {
$name = $attributes['_route']; // this is the field coming from symfony core
$route = $collection->get($name);
$attributes[RouteObjectInterface::ROUTE_OBJECT] = $route;
if ($route instanceof RouteObjectInterface && is_string($route->getRouteKey())) {
$name = $route->getRouteKey();
}
if (empty($attributes['_route_name']) && is_string($name)) {
$attributes['_route_name'] = $name;
if (is_string($name)) {
$attributes[RouteObjectInterface::ROUTE_NAME] = $name;
}
}
......
......@@ -39,8 +39,8 @@ protected function getAttributes(Route $route, $name, array $attributes)
if ($route instanceof RouteObjectInterface && is_string($route->getRouteKey())) {
$name = $route->getRouteKey();
}
$attributes['_route_name'] = $name;
$attributes['_route'] = $route;
$attributes[RouteObjectInterface::ROUTE_NAME] = $name;
$attributes[RouteObjectInterface::ROUTE_OBJECT] = $route;
return $this->mergeDefaults($attributes, $route->getDefaults());
}
}
......@@ -6,6 +6,7 @@
use Symfony\Component\Routing\Exception\RouteNotFoundException;
use Symfony\Component\Routing\Generator\UrlGenerator;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Cmf\Component\Routing\RouteProviderInterface;
......@@ -15,7 +16,7 @@
*
* @author Larry Garfield
*/
class ProviderBasedGenerator extends UrlGenerator
class ProviderBasedGenerator extends UrlGenerator implements VersatileGeneratorInterface
{
/**
* The route provider for this generator.
......@@ -45,13 +46,13 @@ public function generate($name, $parameters = array(), $absolute = false)
$compiledRoute = $route->compile();
// handle symfony 2.1 and 2.2
// getHostnameTokens exists only since 2.2
$hostnameTokens = null;
if (method_exists($compiledRoute, 'getHostnameTokens')) {
$hostnameTokens = $compiledRoute->getHostnameTokens();
// getHostTokens exists only since 2.2
$hostTokens = null;
if (method_exists($compiledRoute, 'getHostTokens')) {
$hostTokens = $compiledRoute->getHostTokens();
}
return $this->doGenerate($compiledRoute->getVariables(), $route->getDefaults(), $route->getRequirements(), $compiledRoute->getTokens(), $parameters, $name, $absolute, $hostnameTokens);
return $this->doGenerate($compiledRoute->getVariables(), $route->getDefaults(), $route->getRequirements(), $compiledRoute->getTokens(), $parameters, $name, $absolute, $hostTokens);
}
/**
......
......@@ -16,6 +16,16 @@
*/
interface RouteObjectInterface
{
/**
* Field name that will hold the route name that was matched.
*/
const ROUTE_NAME = '_route';
/**
* Field name of the route object that was matched.
*/
const ROUTE_OBJECT = '_route_object';
/**
* Constant for the field that is given to the ControllerAliasMapper.
* The value must be configured in the controllers_by_alias mapping.
......
......@@ -5,6 +5,7 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Cmf\Component\Routing\Enhancer\RouteContentEnhancer;
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
use Symfony\Cmf\Component\Routing\Test\CmfUnitTestCase;
......@@ -22,7 +23,7 @@ public function setUp()
$this->document = $this->buildMock('Symfony\\Cmf\\Component\\Routing\\Tests\\Enhancer\\RouteObject',
array('getRouteContent', 'getRouteDefaults', 'getUrl'));
$this->mapper = new RouteContentEnhancer('_route', '_content');
$this->mapper = new RouteContentEnhancer(RouteObjectInterface::ROUTE_OBJECT, '_content');
$this->request = Request::create('/test');
}
......@@ -34,8 +35,8 @@ public function testContent()
->method('getRouteContent')
->will($this->returnValue($targetDocument));
$defaults = array('_route' => $this->document);
$expected = array('_route' => $this->document, '_content' => $targetDocument);
$defaults = array(RouteObjectInterface::ROUTE_OBJECT => $this->document);
$expected = array(RouteObjectInterface::ROUTE_OBJECT => $this->document, '_content' => $targetDocument);
$this->assertEquals($expected, $this->mapper->enhance($defaults, $this->request));
}
......@@ -47,7 +48,7 @@ public function testFieldAlreadyThere()
->method('getRouteContent')
;
$defaults = array('_route' => $this->document, '_content' => 'foo');
$defaults = array(RouteObjectInterface::ROUTE_OBJECT => $this->document, '_content' => 'foo');
$this->assertEquals($defaults, $this->mapper->enhance($defaults, $this->request));
}
......@@ -58,13 +59,13 @@ public function testNoContent()
->method('getRouteContent')
->will($this->returnValue(null));
$defaults = array('_route' => $this->document);
$defaults = array(RouteObjectInterface::ROUTE_OBJECT => $this->document);
$this->assertEquals($defaults, $this->mapper->enhance($defaults, $this->request));
}
public function testNoCmfRoute()
{
$defaults = array('_route' => $this->buildMock('Symfony\\Component\\Routing\\Route'));
$defaults = array(RouteObjectInterface::ROUTE_OBJECT => $this->buildMock('Symfony\\Component\\Routing\\Route'));
$this->assertEquals($defaults, $this->mapper->enhance($defaults, $this->request));
}
}
......
......@@ -51,7 +51,12 @@ public function testMatch()
->method('getDefaults')
->will($this->returnValue(array('foo' => 'bar')))
;
$this->routeDocument->expects($this->any())
->method('getRouteKey')
->will($this->returnValue('/routes/company/more'))
;
// add some other routes to the collection
$mockCompiled = $this->buildMock('Symfony\\Component\\Routing\\CompiledRoute');
$mockCompiled->expects($this->any())
->method('getStaticPrefix')
......@@ -62,6 +67,7 @@ public function testMatch()
->method('compile')
->will($this->returnValue($mockCompiled))
;
$routeCollection = new RouteCollection();
$routeCollection->add('some', $mockRoute);
$routeCollection->add('_company_more', $this->routeDocument);
......@@ -69,9 +75,10 @@ public function testMatch()
$results = $this->matcher->finalMatch($routeCollection, $this->request);
// the matched route returns a key
$expected = array(
'_route_name' => '_company_more',
'_route' => $this->routeDocument,
RouteObjectInterface::ROUTE_NAME => '/routes/company/more',
RouteObjectInterface::ROUTE_OBJECT => $this->routeDocument,
'foo' => 'bar',
);
......@@ -118,9 +125,10 @@ public function testMatchNoRouteObject()
$results = $this->matcher->finalMatch($routeCollection, $this->request);
// the matched route does not return a key
$expected = array(
'_route_name' => '_company_more',
'_route' => $this->routeDocument,
RouteObjectInterface::ROUTE_NAME => '_company_more',
RouteObjectInterface::ROUTE_OBJECT => $this->routeDocument,
'foo' => 'bar',
);
......
......@@ -89,8 +89,8 @@ public function doTestMatchRouteKey($routeKey)
$results = $this->matcher->finalMatch($routeCollection, $this->request);
$expected = array(
'_route_name' => ($routeKey) ? $routeKey : '_company_more',
'_route' => $this->routeDocument,
RouteObjectInterface::ROUTE_NAME => ($routeKey) ? $routeKey : '_company_more',
RouteObjectInterface::ROUTE_OBJECT => $this->routeDocument,
'foo' => 'bar',
);
......@@ -138,8 +138,8 @@ public function testMatchNoRouteObject()
$results = $this->matcher->finalMatch($routeCollection, $this->request);
$expected = array(
'_route_name' => '_company_more',
'_route' => $this->routeDocument,
RouteObjectInterface::ROUTE_NAME => '_company_more',
RouteObjectInterface::ROUTE_OBJECT => $this->routeDocument,
'foo' => 'bar',
);
......
......@@ -278,7 +278,7 @@ public function testSupports()
*/
class TestableContentAwareGenerator extends ContentAwareGenerator
{
protected function doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $absolute, $hostnameTokens = null)
protected function doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $absolute, $hostTokens = null)
{
return 'result_url';
}
......
......@@ -29,7 +29,7 @@ public function setUp()
$this->routeDocument = $this->buildMock('Symfony\\Cmf\\Component\\Routing\\Tests\\Routing\\RouteMock', array('getDefaults'));
$this->matcher = $this->buildMock('Symfony\\Component\\Routing\\Matcher\\UrlMatcherInterface');
$this->generator = $this->buildMock('Symfony\\Component\\Routing\\Generator\\UrlGeneratorInterface', array('supports', 'generate', 'setContext', 'getContext'));
$this->generator = $this->buildMock('Symfony\\Cmf\\Component\\Routing\\VersatileGeneratorInterface', array('supports', 'generate', 'setContext', 'getContext'));
$this->enhancer = $this->buildMock('Symfony\\Cmf\\Component\\Routing\\Enhancer\\RouteEnhancerInterface', array('enhance'));
$this->context = $this->buildMock('Symfony\\Component\\Routing\\RequestContext');
......
......@@ -87,7 +87,7 @@ public function testSupports()
*/
class TestableProviderBasedGenerator extends ProviderBasedGenerator
{
protected function doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $absolute, $hostnameTokens = null)
protected function doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $absolute, $hostTokens = null)
{
return 'result_url';
}
......
<?php
namespace Symfony\Cmf\Component\Routing;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
/**
* This generator is able to handle more than string route names as symfony
* core supports them.
*/
interface VersatileGeneratorInterface extends UrlGeneratorInterface
{
/**
* If $name preg_match this pattern, the name is valid for symfony core
* compatible generators.
*/
const CORE_NAME_PATTERN = '/^[a-z0-9A-Z_.]+$/';
/**
* Whether this generator supports the supplied $name.
*
* This check does not need to look if the specific instance can be
* resolved to a route, only whether the router can generate routes from
* objects of this class.
*
* @param mixed $name The route "name" which may also be an object or anything
*
* @return bool
*/
public function supports($name);
}