diff --git a/core/core.services.yml b/core/core.services.yml index 3a90788..2c882c7 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -450,7 +450,7 @@ services: - [setCurrentUser, ['@?current_user']] access_manager: class: Drupal\Core\Access\AccessManager - arguments: ['@router.route_provider', '@url_generator', '@route_enhancer.param_conversion'] + arguments: ['@router.route_provider', '@url_generator', '@paramconverter_manager'] calls: - [setContainer, ['@service_container']] - [setRequest, ['@?request']] diff --git a/core/lib/Drupal/Core/Access/AccessManager.php b/core/lib/Drupal/Core/Access/AccessManager.php index c6b5155..42fc39a 100644 --- a/core/lib/Drupal/Core/Access/AccessManager.php +++ b/core/lib/Drupal/Core/Access/AccessManager.php @@ -7,19 +7,17 @@ namespace Drupal\Core\Access; -use Drupal\Core\ParamConverter\ParamConverterManager; +use Drupal\Core\ParamConverter\ParamConverterManagerInterface; use Drupal\Core\ParamConverter\ParamNotConvertedException; use Drupal\Core\Routing\Access\AccessInterface as RoutingAccessInterface; use Drupal\Core\Routing\RequestHelper; use Drupal\Core\Routing\RouteProviderInterface; use Drupal\Core\Session\AccountInterface; -use Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerInterface; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; use Symfony\Component\DependencyInjection\ContainerAware; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\Routing\Exception\RouteNotFoundException; use Symfony\Cmf\Component\Routing\RouteObjectInterface; @@ -73,11 +71,11 @@ class AccessManager extends ContainerAware { protected $urlGenerator; /** - * The route enhancer. + * The paramconverter manager. * - * @var \Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerInterface + * @var \Drupal\Core\ParamConverter\ParamConverterManagerInterface */ - protected $routeEnhancer; + protected $paramConverterManager; /** * A request object. @@ -93,13 +91,13 @@ class AccessManager extends ContainerAware { * The route provider. * @param \Symfony\Component\Routing\Generator\UrlGeneratorInterface $url_generator * The url generator. - * @param \Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerInterface $route_enhancer - * The route enhancer. + * @param \Drupal\Core\ParamConverter\ParamConverterManagerInterface $paramconverter_manager + * The param converter manager. */ - public function __construct(RouteProviderInterface $route_provider, UrlGeneratorInterface $url_generator, RouteEnhancerInterface $route_enhancer) { + public function __construct(RouteProviderInterface $route_provider, UrlGeneratorInterface $url_generator, ParamConverterManagerInterface $paramconverter_manager) { $this->routeProvider = $route_provider; $this->urlGenerator = $url_generator; - $this->routeEnhancer = $route_enhancer; + $this->paramConverterManager = $paramconverter_manager; } /** @@ -204,7 +202,7 @@ public function checkNamedRoute($route_name, array $parameters = array(), Accoun $defaults = $parameters + $route->getDefaults(); $route_request = RequestHelper::duplicate($this->request, $this->urlGenerator->generate($route_name, $defaults)); $defaults[RouteObjectInterface::ROUTE_OBJECT] = $route; - $route_request->attributes->add($this->routeEnhancer->enhance($defaults, $route_request)); + $route_request->attributes->add($this->paramConverterManager->convert($defaults, $route_request)); } return $this->check($route, $route_request, $account); } diff --git a/core/lib/Drupal/Core/EventSubscriber/ParamConverterSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/ParamConverterSubscriber.php index 7d385f5..b89e9ff 100644 --- a/core/lib/Drupal/Core/EventSubscriber/ParamConverterSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/ParamConverterSubscriber.php @@ -7,7 +7,7 @@ namespace Drupal\Core\EventSubscriber; -use Drupal\Core\ParamConverter\ParamConverterManager; +use Drupal\Core\ParamConverter\ParamConverterManagerInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Drupal\Core\Routing\RoutingEvents; use Drupal\Core\Routing\RouteBuildEvent; @@ -20,18 +20,18 @@ class ParamConverterSubscriber implements EventSubscriberInterface { /** * The parameter converter manager. * - * @var \Drupal\Core\ParamConverter\ParamConverterManager + * @var \Drupal\Core\ParamConverter\ParamConverterManagerInterface */ protected $paramConverterManager; /** * Constructs a new ParamConverterSubscriber. * - * @param \Drupal\Core\ParamConverter\ParamConverterManager $param_converter_manager + * @param \Drupal\Core\ParamConverter\ParamConverterManagerInterface $param_converter_manager * The parameter converter manager that will be responsible for upcasting * request attributes. */ - public function __construct(ParamConverterManager $param_converter_manager) { + public function __construct(ParamConverterManagerInterface $param_converter_manager) { $this->paramConverterManager = $param_converter_manager; } diff --git a/core/lib/Drupal/Core/EventSubscriber/RouterListener.php b/core/lib/Drupal/Core/EventSubscriber/RouterListener.php index f3d76ca..0c730eb 100644 --- a/core/lib/Drupal/Core/EventSubscriber/RouterListener.php +++ b/core/lib/Drupal/Core/EventSubscriber/RouterListener.php @@ -21,11 +21,13 @@ class RouterListener extends SymfonyRouterListener { * {@inheritdoc} */ public function onKernelRequest(GetResponseEvent $event) { + // Catch failed parameter conversions and throw a 404 instead. This cannot + // be done on the router level as it does not always deal with HTTP. try { parent::onKernelRequest($event); } catch (ParamNotConvertedException $e) { - throw new NotFoundHttpException(); + throw new NotFoundHttpException('', $e); } } diff --git a/core/lib/Drupal/Core/ParamConverter/ParamConverterManager.php b/core/lib/Drupal/Core/ParamConverter/ParamConverterManager.php index 8061522..23d0686 100644 --- a/core/lib/Drupal/Core/ParamConverter/ParamConverterManager.php +++ b/core/lib/Drupal/Core/ParamConverter/ParamConverterManager.php @@ -8,7 +8,9 @@ namespace Drupal\Core\ParamConverter; use Symfony\Component\DependencyInjection\ContainerAware; +use Symfony\Cmf\Component\Routing\RouteObjectInterface; use Symfony\Component\Routing\RouteCollection; +use Symfony\Component\HttpFoundation\Request; /** * Manages converter services for converting request parameters to full objects. @@ -16,7 +18,7 @@ * A typical use case for this would be upcasting (converting) a node id to a * node entity. */ -class ParamConverterManager extends ContainerAware { +class ParamConverterManager extends ContainerAware implements ParamConverterManagerInterface { /** * An array of registered converter service ids. @@ -40,15 +42,7 @@ class ParamConverterManager extends ContainerAware { protected $converters = array(); /** - * Registers a parameter converter with the manager. - * - * @param string $converter - * The parameter converter service id to register. - * @param int $priority - * (optional) The priority of the converter. Defaults to 0. - * - * @return \Drupal\Core\ParamConverter\ParamConverterManager - * The called object for chaining. + * {@inheritdoc} */ public function addConverter($converter, $priority = 0) { if (empty($this->converterIds[$priority])) { @@ -60,10 +54,7 @@ public function addConverter($converter, $priority = 0) { } /** - * Sorts the converter service ids and flattens them. - * - * @return array - * The sorted parameter converter service ids. + * {@inheritdoc} */ public function getConverterIds() { if (!isset($this->sortedConverterIds)) { @@ -77,16 +68,7 @@ public function getConverterIds() { } /** - * Lazy-loads converter services. - * - * @param string $converter - * The service id of converter service to load. - * - * @return \Drupal\Core\ParamConverter\ParamConverterInterface - * The loaded converter service identified by the given service id. - * - * @throws \InvalidArgumentException - * If the given service id is not a registered converter. + * {@inheritdoc} */ public function getConverter($converter) { if (isset($this->converters[$converter])) { @@ -99,10 +81,7 @@ public function getConverter($converter) { } /** - * Saves a list of applicable converters to each route. - * - * @param \Symfony\Component\Routing\RouteCollection $routes - * A collection of routes to apply converters to. + * {@inheritdoc} */ public function setRouteParameterConverters(RouteCollection $routes) { foreach ($routes->all() as $route) { @@ -131,5 +110,40 @@ public function setRouteParameterConverters(RouteCollection $routes) { } } + /** + * {@inheritdoc} + */ + public function convert(array $defaults, Request $request) { + /** @var $route \Symfony\Component\Routing\Route */ + $route = $defaults[RouteObjectInterface::ROUTE_OBJECT]; + + // Skip this enhancer if there are no parameter definitions. + if (!$parameters = $route->getOption('parameters')) { + return $defaults; + } + + // Invoke the registered converter for each parameter. + foreach ($parameters as $name => $definition) { + if (!isset($defaults[$name])) { + // Do not try to convert anything that is already set to NULL. + continue; + } + + if (!isset($definition['converter'])) { + // Continue if no converter has been specified. + continue; + } + + // If a converter returns NULL it means that the parameter could not be + // converted. + $defaults[$name] = $this->getConverter($definition['converter'])->convert($defaults[$name], $definition, $name, $defaults, $request); + if (!isset($defaults[$name])) { + throw new ParamNotConvertedException(sprintf('The "%s" parameter was not converted for the path "%s"', $name, $route->getPath())); + } + } + + return $defaults; + } + } diff --git a/core/lib/Drupal/Core/ParamConverter/ParamConverterManagerInterface.php b/core/lib/Drupal/Core/ParamConverter/ParamConverterManagerInterface.php new file mode 100644 index 0000000..8240e62 --- /dev/null +++ b/core/lib/Drupal/Core/ParamConverter/ParamConverterManagerInterface.php @@ -0,0 +1,77 @@ +paramConverterManager = $param_converter_manager; } @@ -35,46 +34,29 @@ public function __construct(ParamConverterManager $param_converter_manager) { * {@inheritdoc} */ public function enhance(array $defaults, Request $request) { - // Store a backup of the raw $defaults values corresponding to - // variables in the route path pattern. + $defaults['_raw_variables'] = $this->copyRawVariables($defaults); + return $this->paramConverterManager->convert($defaults, $request); + } + + /** + * Store a backup of the raw values that corresponding to the route pattern. + * + * @param array $defaults + * + * @return \Symfony\Component\HttpFoundation\ParameterBag + */ + protected function copyRawVariables(array $defaults) { /** @var $route \Symfony\Component\Routing\Route */ $route = $defaults[RouteObjectInterface::ROUTE_OBJECT]; $variables = array_flip($route->compile()->getVariables()); - // Foreach will copy the values from the array it iterates. Even if they + // Foreach will copy the values from the array it iterates. Even if they // are references, use it to break them. This avoids any scenarios where raw // variables also get replaced with converted values. $raw_variables = array(); foreach (array_intersect_key($defaults, $variables) as $key => $value) { $raw_variables[$key] = $value; } - $defaults['_raw_variables'] = new ParameterBag($raw_variables); - - // Skip this enhancer if there are no parameter definitions. - if (!$parameters = $route->getOption('parameters')) { - return $defaults; - } - - // Invoke the registered converter for each parameter. - foreach ($parameters as $name => $definition) { - if (!isset($defaults[$name])) { - // Do not try to convert anything that is already set to NULL. - continue; - } - - if (!isset($definition['converter'])) { - // Continue if no converter has been specified. - continue; - } - - // If a converter returns NULL it means that the parameter could not be - // converted in which case we throw a 404. - $defaults[$name] = $this->paramConverterManager->getConverter($definition['converter'])->convert($defaults[$name], $definition, $name, $defaults, $request); - if (!isset($defaults[$name])) { - throw new ParamNotConvertedException(sprintf('The "%s" parameter was not converted for the path "%s"', $name, $route->getPath())); - } - } - - return $defaults; + return new ParameterBag($raw_variables); } } diff --git a/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php b/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php index b1e041f..0e830e2 100644 --- a/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php +++ b/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php @@ -63,11 +63,11 @@ class AccessManagerTest extends UnitTestCase { protected $urlGenerator; /** - * The route enhancer. + * The parameter converter. * - * @var \Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Drupal\Core\ParamConverter\ParamConverterManagerInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $routeEnhancer; + protected $paramConverter; /** * The mocked account. @@ -119,11 +119,11 @@ protected function setUp() { ->method('generate') ->will($this->returnValueMap($map)); - $this->routeEnhancer = $this->getMock('Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerInterface'); + $this->paramConverter = $this->getMock('Drupal\Core\ParamConverter\ParamConverterManagerInterface'); $this->account = $this->getMock('Drupal\Core\Session\AccountInterface'); - $this->accessManager = new AccessManager($this->routeProvider, $this->urlGenerator, $this->routeEnhancer, $this->account); + $this->accessManager = new AccessManager($this->routeProvider, $this->urlGenerator, $this->paramConverter, $this->account); $this->accessManager->setContainer($this->container); } @@ -152,7 +152,7 @@ public function testSetChecks() { */ public function testSetChecksWithDynamicAccessChecker() { // Setup the access manager. - $this->accessManager = new AccessManager($this->routeProvider, $this->urlGenerator, $this->routeEnhancer, $this->account); + $this->accessManager = new AccessManager($this->routeProvider, $this->urlGenerator, $this->paramConverter, $this->account); $this->accessManager->setContainer($this->container); // Setup the dynamic access checker. @@ -394,12 +394,12 @@ public function testCheckNamedRoute() { // Tests the access with routes without given request. $this->accessManager->setRequest(new Request()); - $this->routeEnhancer->expects($this->at(0)) - ->method('enhance') + $this->paramConverter->expects($this->at(0)) + ->method('convert') ->will($this->returnValue(array())); - $this->routeEnhancer->expects($this->at(1)) - ->method('enhance') + $this->paramConverter->expects($this->at(1)) + ->method('convert') ->will($this->returnValue(array())); // Tests the access with routes with parameters without given request. @@ -431,9 +431,9 @@ public function testCheckNamedRouteWithUpcastedValues() { ->method('generate') ->will($this->returnValueMap($map)); - $this->routeEnhancer = $this->getMock('Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerInterface'); - $this->routeEnhancer->expects($this->at(0)) - ->method('enhance') + $this->paramConverter = $this->getMock('Drupal\Core\ParamConverter\ParamConverterManagerInterface'); + $this->paramConverter->expects($this->at(0)) + ->method('convert') ->will($this->returnValue(array('value' => 'upcasted_value'))); @@ -444,7 +444,7 @@ public function testCheckNamedRouteWithUpcastedValues() { ->with('/test-route-1/example') ->will($this->returnValue($subrequest)); - $this->accessManager = new AccessManager($this->routeProvider, $this->urlGenerator, $this->routeEnhancer, $this->account); + $this->accessManager = new AccessManager($this->routeProvider, $this->urlGenerator, $this->paramConverter, $this->account); $this->accessManager->setContainer($this->container); $this->accessManager->setRequest(new Request()); @@ -491,9 +491,9 @@ public function testCheckNamedRouteWithDefaultValue() { ->with('test_route_1', array('value' => 'example')) ->will($this->returnValueMap($map)); - $this->routeEnhancer = $this->getMock('Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerInterface'); - $this->routeEnhancer->expects($this->at(0)) - ->method('enhance') + $this->paramConverter = $this->getMock('Drupal\Core\ParamConverter\ParamConverterManagerInterface'); + $this->paramConverter->expects($this->at(0)) + ->method('convert') ->with(array('value' => 'example', RouteObjectInterface::ROUTE_OBJECT => $route)) ->will($this->returnValue(array('value' => 'upcasted_value'))); @@ -504,7 +504,7 @@ public function testCheckNamedRouteWithDefaultValue() { ->with('/test-route-1/example') ->will($this->returnValue($subrequest)); - $this->accessManager = new AccessManager($this->routeProvider, $this->urlGenerator, $this->routeEnhancer, $this->account); + $this->accessManager = new AccessManager($this->routeProvider, $this->urlGenerator, $this->paramConverter, $this->account); $this->accessManager->setContainer($this->container); $this->accessManager->setRequest(new Request()); @@ -578,7 +578,7 @@ public function testCheckException($return_value, $access_mode) { ->will($this->returnValue($return_value)); $container->set('test_incorrect_value', $access_check); - $access_manager = new AccessManager($route_provider, $this->urlGenerator, $this->routeEnhancer); + $access_manager = new AccessManager($route_provider, $this->urlGenerator, $this->paramConverter); $access_manager->setContainer($container); $access_manager->addCheckService('test_incorrect_value'); @@ -633,7 +633,7 @@ protected static function convertAccessCheckInterfaceToString($constant) { * Adds a default access check service to the container and the access manager. */ protected function setupAccessChecker() { - $this->accessManager = new AccessManager($this->routeProvider, $this->urlGenerator, $this->routeEnhancer, $this->account); + $this->accessManager = new AccessManager($this->routeProvider, $this->urlGenerator, $this->paramConverter, $this->account); $this->accessManager->setContainer($this->container); $access_check = new DefaultAccessCheck(); $this->container->register('test_access_default', $access_check); diff --git a/core/tests/Drupal/Tests/Core/Enhancer/ParamConversionEnhancerTest.php b/core/tests/Drupal/Tests/Core/Enhancer/ParamConversionEnhancerTest.php index 42ced7d..f196232 100644 --- a/core/tests/Drupal/Tests/Core/Enhancer/ParamConversionEnhancerTest.php +++ b/core/tests/Drupal/Tests/Core/Enhancer/ParamConversionEnhancerTest.php @@ -27,7 +27,7 @@ class ParamConversionEnhancerTest extends UnitTestCase { protected $paramConversionEnhancer; /** - * @var \Drupal\Core\ParamConverter\ParamConverterManager|\PHPUnit_Framework_MockObject_MockObject + * @var \Drupal\Core\ParamConverter\ParamConverterManagerInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $paramConverterManager; @@ -48,9 +48,7 @@ public static function getInfo() { protected function setUp() { parent::setUp(); - $this->paramConverterManager = $this->getMockBuilder('Drupal\Core\ParamConverter\ParamConverterManager') - ->disableOriginalConstructor() - ->getMock(); + $this->paramConverterManager = $this->getMock('Drupal\Core\ParamConverter\ParamConverterManagerInterface'); $this->paramConversionEnhancer = new ParamConversionEnhancer($this->paramConverterManager); } @@ -59,14 +57,6 @@ protected function setUp() { */ public function testEnhance() { $route = new Route('/test/{id}/{literal}/{null}'); - $parameters = array( - 'id' => array( - 'converter' => 'test_convert', - ), - 'literal' => array(), - 'null' => array(), - ); - $route->setOption('parameters', $parameters); $raw_variables = array( 'id' => 1, @@ -81,15 +71,10 @@ public function testEnhance() { $expected['id'] = 'something_better!'; $expected['_raw_variables'] = new ParameterBag($raw_variables); - $converter = $this->getMock('Drupal\Core\ParamConverter\ParamConverterInterface'); - $converter->expects($this->any()) - ->method('convert') - ->with(1, $this->isType('array'), 'id', $this->isType('array'), $this->isInstanceOf('Symfony\Component\HttpFoundation\Request')) - ->will($this->returnValue('something_better!')); $this->paramConverterManager->expects($this->any()) - ->method('getConverter') - ->with('test_convert') - ->will($this->returnValue($converter)); + ->method('convert') + ->with($this->isType('array'), $this->isInstanceOf('Symfony\Component\HttpFoundation\Request')) + ->will($this->returnValue($expected)); $result = $this->paramConversionEnhancer->enhance($defaults, new Request()); @@ -97,53 +82,21 @@ public function testEnhance() { } /** - * @covers ::enhance() + * @covers ::copyRawVariables() */ - public function testEnhanceNoConverting() { - $route = new Route('/test'); - $defaults = array( - RouteObjectInterface::ROUTE_OBJECT => $route, - ); - - $expected = $defaults; - $expected['_raw_variables'] = new ParameterBag(); - - $result = $this->paramConversionEnhancer->enhance($defaults, new Request()); - $this->assertEquals($expected, $result); - } - - /** - * @covers ::enhance() - * - * @expectedException \Drupal\Core\ParamConverter\ParamNotConvertedException - */ - public function testEnhanceMissingParam() { + public function testCopyRawVariables() { $route = new Route('/test/{id}'); - $parameters = array( - 'id' => array( - 'converter' => 'test_convert', - ), - ); - $route->setOption('parameters', $parameters); - - $raw_variables = array( - 'id' => 1, - ); $defaults = array( RouteObjectInterface::ROUTE_OBJECT => $route, - ) + $raw_variables; - - $converter = $this->getMock('Drupal\Core\ParamConverter\ParamConverterInterface'); - $converter->expects($this->any()) - ->method('convert') - ->with(1, $this->isType('array'), 'id', $this->isType('array'), $this->isInstanceOf('Symfony\Component\HttpFoundation\Request')) - ->will($this->returnValue(NULL)); + 'id' => '1', + ); $this->paramConverterManager->expects($this->any()) - ->method('getConverter') - ->with('test_convert') - ->will($this->returnValue($converter)); - - $this->paramConversionEnhancer->enhance($defaults, new Request()); + ->method('convert') + ->with($this->isType('array'), $this->isInstanceOf('Symfony\Component\HttpFoundation\Request')) + ->will($this->returnArgument(0)); + $expected = new ParameterBag(array('id' => 1)); + $result = $this->paramConversionEnhancer->enhance($defaults, new Request()); + $this->assertEquals($result['_raw_variables'], $expected); } } diff --git a/core/tests/Drupal/Tests/Core/ParamConverter/ParamConverterManagerTest.php b/core/tests/Drupal/Tests/Core/ParamConverter/ParamConverterManagerTest.php index 42ffeca..1d85dc1 100644 --- a/core/tests/Drupal/Tests/Core/ParamConverter/ParamConverterManagerTest.php +++ b/core/tests/Drupal/Tests/Core/ParamConverter/ParamConverterManagerTest.php @@ -9,6 +9,8 @@ use Drupal\Core\ParamConverter\ParamConverterManager; use Drupal\Tests\UnitTestCase; +use Symfony\Cmf\Component\Routing\RouteObjectInterface; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; @@ -216,4 +218,92 @@ public function providerTestSetRouteParameterConverters() { ); } + /** + * @covers ::convert() + */ + public function testConvert() { + $route = new Route('/test/{id}/{literal}/{null}'); + $parameters = array( + 'id' => array( + 'converter' => 'test_convert', + ), + 'literal' => array(), + 'null' => array(), + ); + $route->setOption('parameters', $parameters); + + $defaults = array( + RouteObjectInterface::ROUTE_OBJECT => $route, + 'id' => 1, + 'literal' => 'this is a literal', + 'null' => NULL, + ); + + $expected = $defaults; + $expected['id'] = 'something_better!'; + + $converter = $this->getMock('Drupal\Core\ParamConverter\ParamConverterInterface'); + $converter->expects($this->any()) + ->method('convert') + ->with(1, $this->isType('array'), 'id', $this->isType('array'), $this->isInstanceOf('Symfony\Component\HttpFoundation\Request')) + ->will($this->returnValue('something_better!')); + $this->manager->addConverter('test_convert'); + $this->container->expects($this->once()) + ->method('get') + ->with('test_convert') + ->will($this->returnValue($converter)); + + $result = $this->manager->convert($defaults, new Request()); + + $this->assertEquals($expected, $result); + } + + /** + * @covers ::convert() + */ + public function testConvertNoConverting() { + $route = new Route('/test'); + $defaults = array( + RouteObjectInterface::ROUTE_OBJECT => $route, + ); + + $expected = $defaults; + + $result = $this->manager->convert($defaults, new Request()); + $this->assertEquals($expected, $result); + } + + /** + * @covers ::convert() + * + * @expectedException \Drupal\Core\ParamConverter\ParamNotConvertedException + */ + public function testConvertMissingParam() { + $route = new Route('/test/{id}'); + $parameters = array( + 'id' => array( + 'converter' => 'test_convert', + ), + ); + $route->setOption('parameters', $parameters); + + $defaults = array( + RouteObjectInterface::ROUTE_OBJECT => $route, + 'id' => 1, + ); + + $converter = $this->getMock('Drupal\Core\ParamConverter\ParamConverterInterface'); + $converter->expects($this->any()) + ->method('convert') + ->with(1, $this->isType('array'), 'id', $this->isType('array'), $this->isInstanceOf('Symfony\Component\HttpFoundation\Request')) + ->will($this->returnValue(NULL)); + $this->manager->addConverter('test_convert'); + $this->container->expects($this->once()) + ->method('get') + ->with('test_convert') + ->will($this->returnValue($converter)); + + $this->manager->convert($defaults, new Request()); + } + }