From b6b2cc8157c7b2322f8670707077c0c165ddad49 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Tue, 8 Sep 2015 20:00:11 -0400 Subject: [PATCH 01/18] Adding a new route loader that is able to load routes from a service This makes it possible to list a service as your main routing "resource", making it easily possible to load routes from within a Php class, such as the kernel itself. --- .../Routing/RouteLoaderInterface.php | 29 ++++++++ .../Routing/ServiceRouterLoader.php | 71 ++++++++++++++++++ .../Tests/Routing/ServiceRouterLoaderTest.php | 72 +++++++++++++++++++ 3 files changed, 172 insertions(+) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Routing/RouteLoaderInterface.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Routing/ServiceRouterLoader.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Routing/ServiceRouterLoaderTest.php diff --git a/src/Symfony/Bundle/FrameworkBundle/Routing/RouteLoaderInterface.php b/src/Symfony/Bundle/FrameworkBundle/Routing/RouteLoaderInterface.php new file mode 100644 index 000000000000..8148b5264818 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Routing/RouteLoaderInterface.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Routing; + +use Symfony\Component\Config\Loader\Loader; +use Symfony\Component\Routing\RouteCollection; + +/** + * Defines a class that is able to load and return a RouteCollection + * + * @author Ryan Weaver + */ +interface RouteLoaderInterface +{ + /** + * @param Loader $loader + * @return RouteCollection + */ + public function getRouteCollection(Loader $loader); +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Routing/ServiceRouterLoader.php b/src/Symfony/Bundle/FrameworkBundle/Routing/ServiceRouterLoader.php new file mode 100644 index 000000000000..eb38b42853e9 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Routing/ServiceRouterLoader.php @@ -0,0 +1,71 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Routing; + +use Symfony\Component\Config\Loader\Loader; +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\Routing\RouteCollection; + +/** + * A route loader that executes a service to load the routes. + * + * @author Ryan Weaver + */ +class ServiceRouterLoader extends Loader +{ + /** + * @var ContainerInterface + */ + private $container; + + public function __construct(ContainerInterface $container) + { + $this->container = $container; + } + + /** + * Calls the service that will load the routes + * + * @param string $resource The name of the service to load + * @param string|null $type The resource type + * + * @return RouteCollection + */ + public function load($resource, $type = null) + { + $service = $this->container->get($resource); + + if (!$service instanceof RouteLoaderInterface) { + throw new \LogicException(sprintf('Service "%s" must implement RouteProviderInterface.', $resource)); + } + + $routeCollection = $service->getRouteCollection($this); + + // make the service file tracked so that if it changes, the cache rebuilds + $obj = new \ReflectionObject($service); + $resource = new FileResource($obj->getFileName()); + $routeCollection->addResource($resource); + + return $routeCollection; + } + + /** + * {@inheritdoc} + * + * @api + */ + public function supports($resource, $type = null) + { + return $type == 'service'; + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/ServiceRouterLoaderTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/ServiceRouterLoaderTest.php new file mode 100644 index 000000000000..be077b1eaa37 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/ServiceRouterLoaderTest.php @@ -0,0 +1,72 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Routing; + +use Symfony\Bundle\FrameworkBundle\Routing\ServiceRouterLoader; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +class ServiceRouterLoaderTest extends \PHPUnit_Framework_TestCase +{ + public function testLoadCallsServiceAndReturnsCollection() + { + $routeLoader = $this->getMock('Symfony\Bundle\FrameworkBundle\Routing\RouteLoaderInterface'); + + $container = $this->getMock('Symfony\\Component\\DependencyInjection\\Container', array('get')); + + $container + ->expects($this->once()) + ->method('get') + ->with('my_route_provider_service') + ->will($this->returnValue($routeLoader)) + ; + + $serviceRouteLoader = new ServiceRouterLoader($container); + + // create a basic collection that will be returned + $routes = new RouteCollection(); + $routes->add('foo', new Route('/foo')); + + $routeLoader + ->expects($this->once()) + ->method('getRouteCollection') + // the loader itself is passed + ->with($serviceRouteLoader) + ->will($this->returnValue($routes)); + + $actualRoutes = $serviceRouteLoader->load('my_route_provider_service', 'service'); + + $this->assertSame($routes, $actualRoutes); + // the service file should be listed as a resource + $this->assertNotEmpty($actualRoutes->getResources()); + } + + /** + * @expectedException \LogicException + */ + public function testExceptionOnInterfaceNotImplemented() + { + // anything that doesn't implement the interface + $routeLoader = new \stdClass(); + + $container = $this->getMock('Symfony\\Component\\DependencyInjection\\Container', array('get')); + + $container + ->expects($this->once()) + ->method('get') + ->will($this->returnValue($routeLoader)) + ; + + $serviceRouteLoader = new ServiceRouterLoader($container); + $serviceRouteLoader->load('any_service_name', 'service'); + } +} From 423f6b02c8161c430e2b7edbd48a04bede490032 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Tue, 8 Sep 2015 20:07:29 -0400 Subject: [PATCH 02/18] Registering the route loader as a service --- .../Bundle/FrameworkBundle/Resources/config/routing.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml index a750027406ec..05f671aef36c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml @@ -50,6 +50,11 @@ + + + + + From ca1229f28c25172189abf86b0777fdbefebc3c19 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Wed, 9 Sep 2015 11:53:27 -0400 Subject: [PATCH 03/18] fabbot! --- .../Bundle/FrameworkBundle/Routing/RouteLoaderInterface.php | 3 ++- .../Bundle/FrameworkBundle/Routing/ServiceRouterLoader.php | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Routing/RouteLoaderInterface.php b/src/Symfony/Bundle/FrameworkBundle/Routing/RouteLoaderInterface.php index 8148b5264818..05976f9bf195 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Routing/RouteLoaderInterface.php +++ b/src/Symfony/Bundle/FrameworkBundle/Routing/RouteLoaderInterface.php @@ -15,7 +15,7 @@ use Symfony\Component\Routing\RouteCollection; /** - * Defines a class that is able to load and return a RouteCollection + * Defines a class that is able to load and return a RouteCollection. * * @author Ryan Weaver */ @@ -23,6 +23,7 @@ interface RouteLoaderInterface { /** * @param Loader $loader + * * @return RouteCollection */ public function getRouteCollection(Loader $loader); diff --git a/src/Symfony/Bundle/FrameworkBundle/Routing/ServiceRouterLoader.php b/src/Symfony/Bundle/FrameworkBundle/Routing/ServiceRouterLoader.php index eb38b42853e9..37f256c4f319 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Routing/ServiceRouterLoader.php +++ b/src/Symfony/Bundle/FrameworkBundle/Routing/ServiceRouterLoader.php @@ -34,10 +34,10 @@ public function __construct(ContainerInterface $container) } /** - * Calls the service that will load the routes + * Calls the service that will load the routes. * - * @param string $resource The name of the service to load - * @param string|null $type The resource type + * @param string $resource The name of the service to load + * @param string|null $type The resource type * * @return RouteCollection */ From cf7af643d08ae4636de4e8f93386f41d8f0fc327 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Thu, 10 Sep 2015 10:28:59 -0400 Subject: [PATCH 04/18] Moving the ServiceRouteLoader stuff into the Routing component as an optional feature --- .../Bundle/FrameworkBundle/Resources/config/routing.xml | 2 +- .../Routing/Loader}/RouteLoaderInterface.php | 2 +- .../Routing/Loader}/ServiceRouterLoader.php | 6 ++++-- .../Routing/Tests/Loader}/ServiceRouterLoaderTest.php | 6 +++--- src/Symfony/Component/Routing/composer.json | 3 ++- 5 files changed, 11 insertions(+), 8 deletions(-) rename src/Symfony/{Bundle/FrameworkBundle/Routing => Component/Routing/Loader}/RouteLoaderInterface.php (92%) rename src/Symfony/{Bundle/FrameworkBundle/Routing => Component/Routing/Loader}/ServiceRouterLoader.php (92%) rename src/Symfony/{Bundle/FrameworkBundle/Tests/Routing => Component/Routing/Tests/Loader}/ServiceRouterLoaderTest.php (90%) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml index 05f671aef36c..f1d540c274a5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml @@ -50,7 +50,7 @@ - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Routing/RouteLoaderInterface.php b/src/Symfony/Component/Routing/Loader/RouteLoaderInterface.php similarity index 92% rename from src/Symfony/Bundle/FrameworkBundle/Routing/RouteLoaderInterface.php rename to src/Symfony/Component/Routing/Loader/RouteLoaderInterface.php index 05976f9bf195..d0430afd0814 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Routing/RouteLoaderInterface.php +++ b/src/Symfony/Component/Routing/Loader/RouteLoaderInterface.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\Bundle\FrameworkBundle\Routing; +namespace Symfony\Component\Routing\Loader; use Symfony\Component\Config\Loader\Loader; use Symfony\Component\Routing\RouteCollection; diff --git a/src/Symfony/Bundle/FrameworkBundle/Routing/ServiceRouterLoader.php b/src/Symfony/Component/Routing/Loader/ServiceRouterLoader.php similarity index 92% rename from src/Symfony/Bundle/FrameworkBundle/Routing/ServiceRouterLoader.php rename to src/Symfony/Component/Routing/Loader/ServiceRouterLoader.php index 37f256c4f319..c33d136d94e2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Routing/ServiceRouterLoader.php +++ b/src/Symfony/Component/Routing/Loader/ServiceRouterLoader.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\Bundle\FrameworkBundle\Routing; +namespace Symfony\Component\Routing\Loader; use Symfony\Component\Config\Loader\Loader; use Symfony\Component\Config\Resource\FileResource; @@ -19,6 +19,8 @@ /** * A route loader that executes a service to load the routes. * + * The depends on the DependencyInjection component + * * @author Ryan Weaver */ class ServiceRouterLoader extends Loader @@ -46,7 +48,7 @@ public function load($resource, $type = null) $service = $this->container->get($resource); if (!$service instanceof RouteLoaderInterface) { - throw new \LogicException(sprintf('Service "%s" must implement RouteProviderInterface.', $resource)); + throw new \LogicException(sprintf('Service "%s" must implement RouteLoaderInterface.', $resource)); } $routeCollection = $service->getRouteCollection($this); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/ServiceRouterLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/ServiceRouterLoaderTest.php similarity index 90% rename from src/Symfony/Bundle/FrameworkBundle/Tests/Routing/ServiceRouterLoaderTest.php rename to src/Symfony/Component/Routing/Tests/Loader/ServiceRouterLoaderTest.php index be077b1eaa37..bf6da30c2cf4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/ServiceRouterLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/ServiceRouterLoaderTest.php @@ -9,9 +9,9 @@ * file that was distributed with this source code. */ -namespace Symfony\Bundle\FrameworkBundle\Tests\Routing; +namespace Symfony\Component\Routing\Tests\Loader; -use Symfony\Bundle\FrameworkBundle\Routing\ServiceRouterLoader; +use Symfony\Component\Routing\Loader\ServiceRouterLoader; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; @@ -19,7 +19,7 @@ class ServiceRouterLoaderTest extends \PHPUnit_Framework_TestCase { public function testLoadCallsServiceAndReturnsCollection() { - $routeLoader = $this->getMock('Symfony\Bundle\FrameworkBundle\Routing\RouteLoaderInterface'); + $routeLoader = $this->getMock('Symfony\Component\Routing\Loader\RouteLoaderInterface'); $container = $this->getMock('Symfony\\Component\\DependencyInjection\\Container', array('get')); diff --git a/src/Symfony/Component/Routing/composer.json b/src/Symfony/Component/Routing/composer.json index b7d4c0aa2bdb..3fad06e80612 100644 --- a/src/Symfony/Component/Routing/composer.json +++ b/src/Symfony/Component/Routing/composer.json @@ -35,7 +35,8 @@ "symfony/config": "For using the all-in-one router or any loader", "symfony/yaml": "For using the YAML loader", "symfony/expression-language": "For using expression matching", - "doctrine/annotations": "For using the annotation loader" + "doctrine/annotations": "For using the annotation loader", + "symfony/dependency-injection": "For loading routes from a service" }, "autoload": { "psr-4": { "Symfony\\Component\\Routing\\": "" } From 5d34c96a2ae1dbf87bfadf5b5f3346f2a39b7b97 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Thu, 10 Sep 2015 10:34:26 -0400 Subject: [PATCH 05/18] Some tweaks thanks to @jakzal --- src/Symfony/Component/Routing/Loader/ServiceRouterLoader.php | 2 +- .../Routing/Tests/Loader/ServiceRouterLoaderTest.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Routing/Loader/ServiceRouterLoader.php b/src/Symfony/Component/Routing/Loader/ServiceRouterLoader.php index c33d136d94e2..2b0b32e2787a 100644 --- a/src/Symfony/Component/Routing/Loader/ServiceRouterLoader.php +++ b/src/Symfony/Component/Routing/Loader/ServiceRouterLoader.php @@ -68,6 +68,6 @@ public function load($resource, $type = null) */ public function supports($resource, $type = null) { - return $type == 'service'; + return 'service' === $type; } } diff --git a/src/Symfony/Component/Routing/Tests/Loader/ServiceRouterLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/ServiceRouterLoaderTest.php index bf6da30c2cf4..9b51a520f4c3 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/ServiceRouterLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/ServiceRouterLoaderTest.php @@ -24,7 +24,7 @@ public function testLoadCallsServiceAndReturnsCollection() $container = $this->getMock('Symfony\\Component\\DependencyInjection\\Container', array('get')); $container - ->expects($this->once()) + ->expects($this->any()) ->method('get') ->with('my_route_provider_service') ->will($this->returnValue($routeLoader)) @@ -37,7 +37,7 @@ public function testLoadCallsServiceAndReturnsCollection() $routes->add('foo', new Route('/foo')); $routeLoader - ->expects($this->once()) + ->expects($this->any()) ->method('getRouteCollection') // the loader itself is passed ->with($serviceRouteLoader) From c129cdd85bcfd6e8d9aa6ab1fea8e71dd0625be8 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Thu, 10 Sep 2015 10:35:28 -0400 Subject: [PATCH 06/18] Hinting against the interface I kind of don't want this, because I'd rather promise the user that there is an "import" function. But, I think it is feasible that someone wants to use this, but has simple loaders that don't have the ability to import (i.e. don't extend Loader). --- .../Component/Routing/Loader/RouteLoaderInterface.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Routing/Loader/RouteLoaderInterface.php b/src/Symfony/Component/Routing/Loader/RouteLoaderInterface.php index d0430afd0814..dd0af02d830e 100644 --- a/src/Symfony/Component/Routing/Loader/RouteLoaderInterface.php +++ b/src/Symfony/Component/Routing/Loader/RouteLoaderInterface.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Routing\Loader; -use Symfony\Component\Config\Loader\Loader; +use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\Routing\RouteCollection; /** @@ -22,9 +22,9 @@ interface RouteLoaderInterface { /** - * @param Loader $loader + * @param LoaderInterface $loader * * @return RouteCollection */ - public function getRouteCollection(Loader $loader); + public function getRouteCollection(LoaderInterface $loader); } From 8440be29d54eb44237ed4598b6c01dafecc08b0a Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sun, 13 Sep 2015 13:52:20 -0400 Subject: [PATCH 07/18] Adding the entire class hierarchy as a resource The addClassResource() was taken from ContainerBuilder --- .../Component/Routing/Loader/ServiceRouterLoader.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Routing/Loader/ServiceRouterLoader.php b/src/Symfony/Component/Routing/Loader/ServiceRouterLoader.php index 2b0b32e2787a..3da4459efdfe 100644 --- a/src/Symfony/Component/Routing/Loader/ServiceRouterLoader.php +++ b/src/Symfony/Component/Routing/Loader/ServiceRouterLoader.php @@ -54,9 +54,7 @@ public function load($resource, $type = null) $routeCollection = $service->getRouteCollection($this); // make the service file tracked so that if it changes, the cache rebuilds - $obj = new \ReflectionObject($service); - $resource = new FileResource($obj->getFileName()); - $routeCollection->addResource($resource); + $this->addClassResource(new \ReflectionClass($service), $routeCollection); return $routeCollection; } @@ -70,4 +68,11 @@ public function supports($resource, $type = null) { return 'service' === $type; } + + private function addClassResource(\ReflectionClass $class, RouteCollection $collection) + { + do { + $collection->addResource(new FileResource($class->getFileName())); + } while ($class = $class->getParentClass()); + } } From 2bb0adc2418abde70769444597d714efb9435acb Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sun, 13 Sep 2015 21:25:56 -0400 Subject: [PATCH 08/18] Fixing typo --- src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml index f1d540c274a5..cb06b99907f4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml @@ -50,7 +50,7 @@ - + From ee904129f4c9006564cac56ca518810dd905afd4 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Tue, 22 Sep 2015 19:29:02 -0400 Subject: [PATCH 09/18] Fixing comment typo --- src/Symfony/Component/Routing/Loader/ServiceRouterLoader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Routing/Loader/ServiceRouterLoader.php b/src/Symfony/Component/Routing/Loader/ServiceRouterLoader.php index 3da4459efdfe..f62336b7a9cd 100644 --- a/src/Symfony/Component/Routing/Loader/ServiceRouterLoader.php +++ b/src/Symfony/Component/Routing/Loader/ServiceRouterLoader.php @@ -19,7 +19,7 @@ /** * A route loader that executes a service to load the routes. * - * The depends on the DependencyInjection component + * This depends on the DependencyInjection component. * * @author Ryan Weaver */ From de4143ad6a54b887a8d049664d21a983ccec249e Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Wed, 23 Sep 2015 22:40:34 -0400 Subject: [PATCH 10/18] Fixing test - bad mock --- .../Routing/Tests/Loader/ServiceRouterLoaderTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Routing/Tests/Loader/ServiceRouterLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/ServiceRouterLoaderTest.php index 9b51a520f4c3..cda8852fee05 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/ServiceRouterLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/ServiceRouterLoaderTest.php @@ -21,7 +21,7 @@ public function testLoadCallsServiceAndReturnsCollection() { $routeLoader = $this->getMock('Symfony\Component\Routing\Loader\RouteLoaderInterface'); - $container = $this->getMock('Symfony\\Component\\DependencyInjection\\Container', array('get')); + $container = $this->getMock('Symfony\\Component\\DependencyInjection\\ContainerInterface', array('get')); $container ->expects($this->any()) @@ -58,7 +58,7 @@ public function testExceptionOnInterfaceNotImplemented() // anything that doesn't implement the interface $routeLoader = new \stdClass(); - $container = $this->getMock('Symfony\\Component\\DependencyInjection\\Container', array('get')); + $container = $this->getMock('Symfony\\Component\\DependencyInjection\\ContainerInterface', array('get')); $container ->expects($this->once()) From eb47a69ab4c0a6394ec78a0b5f2fe8d832881d9d Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sat, 26 Sep 2015 10:37:43 -0400 Subject: [PATCH 11/18] Fixing bad mock of "abstract" class --- .../Routing/Tests/Loader/ServiceRouterLoaderTest.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Routing/Tests/Loader/ServiceRouterLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/ServiceRouterLoaderTest.php index cda8852fee05..793df697f14c 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/ServiceRouterLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/ServiceRouterLoaderTest.php @@ -21,7 +21,7 @@ public function testLoadCallsServiceAndReturnsCollection() { $routeLoader = $this->getMock('Symfony\Component\Routing\Loader\RouteLoaderInterface'); - $container = $this->getMock('Symfony\\Component\\DependencyInjection\\ContainerInterface', array('get')); + $container = $this->getMockedContainer(); $container ->expects($this->any()) @@ -58,7 +58,7 @@ public function testExceptionOnInterfaceNotImplemented() // anything that doesn't implement the interface $routeLoader = new \stdClass(); - $container = $this->getMock('Symfony\\Component\\DependencyInjection\\ContainerInterface', array('get')); + $container = $this->getMockedContainer(); $container ->expects($this->once()) @@ -69,4 +69,11 @@ public function testExceptionOnInterfaceNotImplemented() $serviceRouteLoader = new ServiceRouterLoader($container); $serviceRouteLoader->load('any_service_name', 'service'); } + + private function getMockedContainer() + { + return $this->getMockBuilder('Symfony\\Component\\DependencyInjection\\ContainerInterface') + //->setMethods(array('get')) + ->getMockForAbstractClass(); + } } From 3cb24eb5a54f7ed2c89a7b5c41b815e5388d7772 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Tue, 29 Sep 2015 23:18:42 -0400 Subject: [PATCH 12/18] Changing this to be an abstract ObjectRouteLoader --- ...RouterLoader.php => ObjectRouteLoader.php} | 38 ++++++++--------- ...aderTest.php => ObjectRouteLoaderTest.php} | 42 ++++++++----------- 2 files changed, 36 insertions(+), 44 deletions(-) rename src/Symfony/Component/Routing/Loader/{ServiceRouterLoader.php => ObjectRouteLoader.php} (66%) rename src/Symfony/Component/Routing/Tests/Loader/{ServiceRouterLoaderTest.php => ObjectRouteLoaderTest.php} (61%) diff --git a/src/Symfony/Component/Routing/Loader/ServiceRouterLoader.php b/src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php similarity index 66% rename from src/Symfony/Component/Routing/Loader/ServiceRouterLoader.php rename to src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php index f62336b7a9cd..bb2bb0dbef8b 100644 --- a/src/Symfony/Component/Routing/Loader/ServiceRouterLoader.php +++ b/src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php @@ -13,28 +13,15 @@ use Symfony\Component\Config\Loader\Loader; use Symfony\Component\Config\Resource\FileResource; -use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\Routing\RouteCollection; /** - * A route loader that executes a service to load the routes. - * - * This depends on the DependencyInjection component. + * A route loader that calls a method on an object to load the routes. * * @author Ryan Weaver */ -class ServiceRouterLoader extends Loader +abstract class ObjectRouteLoader extends Loader { - /** - * @var ContainerInterface - */ - private $container; - - public function __construct(ContainerInterface $container) - { - $this->container = $container; - } - /** * Calls the service that will load the routes. * @@ -45,16 +32,16 @@ public function __construct(ContainerInterface $container) */ public function load($resource, $type = null) { - $service = $this->container->get($resource); + $routeLoader = $this->getRouteLoader($resource); - if (!$service instanceof RouteLoaderInterface) { + if (!$routeLoader instanceof RouteLoaderInterface) { throw new \LogicException(sprintf('Service "%s" must implement RouteLoaderInterface.', $resource)); } - $routeCollection = $service->getRouteCollection($this); + $routeCollection = $routeLoader->getRouteCollection($this); // make the service file tracked so that if it changes, the cache rebuilds - $this->addClassResource(new \ReflectionClass($service), $routeCollection); + $this->addClassResource(new \ReflectionClass($routeLoader), $routeCollection); return $routeCollection; } @@ -66,9 +53,20 @@ public function load($resource, $type = null) */ public function supports($resource, $type = null) { - return 'service' === $type; + return 'object' === $type; } + /** + * Returns a RouteLoaderInterface object matching the id. + * + * For example, if your application uses a service container, + * the $id may be a service id. + * + * @param string $id + * @return RouteLoaderInterface + */ + abstract protected function getRouteLoader($id); + private function addClassResource(\ReflectionClass $class, RouteCollection $collection) { do { diff --git a/src/Symfony/Component/Routing/Tests/Loader/ServiceRouterLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/ObjectRouteLoaderTest.php similarity index 61% rename from src/Symfony/Component/Routing/Tests/Loader/ServiceRouterLoaderTest.php rename to src/Symfony/Component/Routing/Tests/Loader/ObjectRouteLoaderTest.php index 793df697f14c..be11ffc3c0e0 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/ServiceRouterLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/ObjectRouteLoaderTest.php @@ -11,26 +11,21 @@ namespace Symfony\Component\Routing\Tests\Loader; -use Symfony\Component\Routing\Loader\ServiceRouterLoader; +use Symfony\Component\Routing\Loader\ObjectRouteLoader; +use Symfony\Component\Routing\Loader\RouteLoaderInterface; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; -class ServiceRouterLoaderTest extends \PHPUnit_Framework_TestCase +class ObjectRouteLoaderTest extends \PHPUnit_Framework_TestCase { public function testLoadCallsServiceAndReturnsCollection() { $routeLoader = $this->getMock('Symfony\Component\Routing\Loader\RouteLoaderInterface'); + $serviceRouteLoader = new ObjectRouteLoaderForTest(); - $container = $this->getMockedContainer(); - - $container - ->expects($this->any()) - ->method('get') - ->with('my_route_provider_service') - ->will($this->returnValue($routeLoader)) - ; - - $serviceRouteLoader = new ServiceRouterLoader($container); + $serviceRouteLoader->loaderMap = array( + 'my_route_provider_service' => $routeLoader + ); // create a basic collection that will be returned $routes = new RouteCollection(); @@ -58,22 +53,21 @@ public function testExceptionOnInterfaceNotImplemented() // anything that doesn't implement the interface $routeLoader = new \stdClass(); - $container = $this->getMockedContainer(); - - $container - ->expects($this->once()) - ->method('get') - ->will($this->returnValue($routeLoader)) - ; + $serviceRouteLoader = new ObjectRouteLoaderForTest(); + $serviceRouteLoader->loaderMap = array( + 'any_service_name' => $routeLoader + ); - $serviceRouteLoader = new ServiceRouterLoader($container); $serviceRouteLoader->load('any_service_name', 'service'); } +} + +class ObjectRouteLoaderForTest extends ObjectRouteLoader +{ + public $loaderMap = array(); - private function getMockedContainer() + protected function getRouteLoader($id) { - return $this->getMockBuilder('Symfony\\Component\\DependencyInjection\\ContainerInterface') - //->setMethods(array('get')) - ->getMockForAbstractClass(); + return isset($this->loaderMap[$id]) ? $this->loaderMap[$id] : null; } } From e431fc78aa207a754119d5cc20228ade6c54da26 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Tue, 29 Sep 2015 23:22:17 -0400 Subject: [PATCH 13/18] Adding a ServiceRouterLoader that works with the DependencyInjection component --- .../Resources/config/routing.xml | 2 +- .../ServiceRouterLoader.php | 44 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Component/Routing/Loader/DependencyInjection/ServiceRouterLoader.php diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml index cb06b99907f4..22aa26e2fbf4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml @@ -50,7 +50,7 @@ - + diff --git a/src/Symfony/Component/Routing/Loader/DependencyInjection/ServiceRouterLoader.php b/src/Symfony/Component/Routing/Loader/DependencyInjection/ServiceRouterLoader.php new file mode 100644 index 000000000000..1e0ead8dc96d --- /dev/null +++ b/src/Symfony/Component/Routing/Loader/DependencyInjection/ServiceRouterLoader.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader\DependencyInjection; + +use Symfony\Component\Config\Loader\Loader; +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\Routing\Loader\ObjectRouteLoader; +use Symfony\Component\Routing\Loader\RouteLoaderInterface; +use Symfony\Component\Routing\RouteCollection; + +/** + * A route loader that executes a service to load the routes. + * + * This depends on the DependencyInjection component. + * + * @author Ryan Weaver + */ +class ServiceRouterLoader extends ObjectRouteLoader +{ + /** + * @var ContainerInterface + */ + private $container; + + public function __construct(ContainerInterface $container) + { + $this->container = $container; + } + + protected function getRouteLoader($id) + { + return $this->container->get($id); + } +} From 43e9ad2a90ffd339848500478b14d3fb68a7ca90 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Tue, 29 Sep 2015 23:24:15 -0400 Subject: [PATCH 14/18] Renaming abstract method and going back to the key "service" as the type --- .../Loader/DependencyInjection/ServiceRouterLoader.php | 2 +- src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php | 6 +++--- .../Routing/Tests/Loader/ObjectRouteLoaderTest.php | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Routing/Loader/DependencyInjection/ServiceRouterLoader.php b/src/Symfony/Component/Routing/Loader/DependencyInjection/ServiceRouterLoader.php index 1e0ead8dc96d..4eb5aa3927f1 100644 --- a/src/Symfony/Component/Routing/Loader/DependencyInjection/ServiceRouterLoader.php +++ b/src/Symfony/Component/Routing/Loader/DependencyInjection/ServiceRouterLoader.php @@ -37,7 +37,7 @@ public function __construct(ContainerInterface $container) $this->container = $container; } - protected function getRouteLoader($id) + protected function getRouteLoaderService($id) { return $this->container->get($id); } diff --git a/src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php b/src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php index bb2bb0dbef8b..b4a83c51a2d2 100644 --- a/src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php +++ b/src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php @@ -32,7 +32,7 @@ abstract class ObjectRouteLoader extends Loader */ public function load($resource, $type = null) { - $routeLoader = $this->getRouteLoader($resource); + $routeLoader = $this->getRouteLoaderService($resource); if (!$routeLoader instanceof RouteLoaderInterface) { throw new \LogicException(sprintf('Service "%s" must implement RouteLoaderInterface.', $resource)); @@ -53,7 +53,7 @@ public function load($resource, $type = null) */ public function supports($resource, $type = null) { - return 'object' === $type; + return 'service' === $type; } /** @@ -65,7 +65,7 @@ public function supports($resource, $type = null) * @param string $id * @return RouteLoaderInterface */ - abstract protected function getRouteLoader($id); + abstract protected function getRouteLoaderService($id); private function addClassResource(\ReflectionClass $class, RouteCollection $collection) { diff --git a/src/Symfony/Component/Routing/Tests/Loader/ObjectRouteLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/ObjectRouteLoaderTest.php index be11ffc3c0e0..71ad8e003da5 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/ObjectRouteLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/ObjectRouteLoaderTest.php @@ -66,7 +66,7 @@ class ObjectRouteLoaderForTest extends ObjectRouteLoader { public $loaderMap = array(); - protected function getRouteLoader($id) + protected function getRouteLoaderService($id) { return isset($this->loaderMap[$id]) ? $this->loaderMap[$id] : null; } From 7ed22ce5fe04ab2fd3918e28b08819b9803e5a6e Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Wed, 30 Sep 2015 19:04:08 -0400 Subject: [PATCH 15/18] fabbot --- .../Loader/DependencyInjection/ServiceRouterLoader.php | 3 --- src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php | 1 + .../Component/Routing/Tests/Loader/ObjectRouteLoaderTest.php | 5 ++--- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/Routing/Loader/DependencyInjection/ServiceRouterLoader.php b/src/Symfony/Component/Routing/Loader/DependencyInjection/ServiceRouterLoader.php index 4eb5aa3927f1..3cf4f26d2af1 100644 --- a/src/Symfony/Component/Routing/Loader/DependencyInjection/ServiceRouterLoader.php +++ b/src/Symfony/Component/Routing/Loader/DependencyInjection/ServiceRouterLoader.php @@ -12,11 +12,8 @@ namespace Symfony\Component\Routing\Loader\DependencyInjection; use Symfony\Component\Config\Loader\Loader; -use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\Routing\Loader\ObjectRouteLoader; -use Symfony\Component\Routing\Loader\RouteLoaderInterface; -use Symfony\Component\Routing\RouteCollection; /** * A route loader that executes a service to load the routes. diff --git a/src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php b/src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php index b4a83c51a2d2..e31df5c92c04 100644 --- a/src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php +++ b/src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php @@ -63,6 +63,7 @@ public function supports($resource, $type = null) * the $id may be a service id. * * @param string $id + * * @return RouteLoaderInterface */ abstract protected function getRouteLoaderService($id); diff --git a/src/Symfony/Component/Routing/Tests/Loader/ObjectRouteLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/ObjectRouteLoaderTest.php index 71ad8e003da5..a1439aa9a755 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/ObjectRouteLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/ObjectRouteLoaderTest.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Routing\Tests\Loader; use Symfony\Component\Routing\Loader\ObjectRouteLoader; -use Symfony\Component\Routing\Loader\RouteLoaderInterface; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; @@ -24,7 +23,7 @@ public function testLoadCallsServiceAndReturnsCollection() $serviceRouteLoader = new ObjectRouteLoaderForTest(); $serviceRouteLoader->loaderMap = array( - 'my_route_provider_service' => $routeLoader + 'my_route_provider_service' => $routeLoader, ); // create a basic collection that will be returned @@ -55,7 +54,7 @@ public function testExceptionOnInterfaceNotImplemented() $serviceRouteLoader = new ObjectRouteLoaderForTest(); $serviceRouteLoader->loaderMap = array( - 'any_service_name' => $routeLoader + 'any_service_name' => $routeLoader, ); $serviceRouteLoader->load('any_service_name', 'service'); From 6b0a5c6785a9fbb610130cf7e4c3f59a373f553d Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Thu, 1 Oct 2015 14:07:19 -0400 Subject: [PATCH 16/18] Updating ObjectRouteLoader to use a service_id:methodName format --- .../ServiceRouterLoader.php | 2 +- .../Routing/Loader/ObjectRouteLoader.php | 54 +++++++---- .../Routing/Loader/RouteLoaderInterface.php | 30 ------ .../Tests/Loader/ObjectRouteLoaderTest.php | 94 ++++++++++++++----- 4 files changed, 106 insertions(+), 74 deletions(-) delete mode 100644 src/Symfony/Component/Routing/Loader/RouteLoaderInterface.php diff --git a/src/Symfony/Component/Routing/Loader/DependencyInjection/ServiceRouterLoader.php b/src/Symfony/Component/Routing/Loader/DependencyInjection/ServiceRouterLoader.php index 3cf4f26d2af1..daa0a15dacbf 100644 --- a/src/Symfony/Component/Routing/Loader/DependencyInjection/ServiceRouterLoader.php +++ b/src/Symfony/Component/Routing/Loader/DependencyInjection/ServiceRouterLoader.php @@ -34,7 +34,7 @@ public function __construct(ContainerInterface $container) $this->container = $container; } - protected function getRouteLoaderService($id) + protected function getServiceObject($id) { return $this->container->get($id); } diff --git a/src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php b/src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php index e31df5c92c04..2a4203f06abd 100644 --- a/src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php +++ b/src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php @@ -22,26 +22,56 @@ */ abstract class ObjectRouteLoader extends Loader { + /** + * Returns the object that the method will be called on to load routes. + * + * For example, if your application uses a service container, + * the $id may be a service id. + * + * @param string $id + * + * @return object + */ + abstract protected function getServiceObject($id); + /** * Calls the service that will load the routes. * - * @param string $resource The name of the service to load + * @param mixed $resource Some value that will resolve to a callable * @param string|null $type The resource type * * @return RouteCollection */ public function load($resource, $type = null) { - $routeLoader = $this->getRouteLoaderService($resource); + $parts = explode(':', $resource); + if (count($parts) != 2) { + throw new \InvalidArgumentException(sprintf('Invalid resource "%s" passed to the "service" route loader: use the format "service_name:methodName"', $resource)); + } + + $serviceString = $parts[0]; + $method = $parts[1]; + + $loaderObject = $this->getServiceObject($serviceString); + + if (!is_object($loaderObject)) { + throw new \LogicException(sprintf('%s:getServiceObject() must return an object: %s returned', get_class($this), $loaderObject)); + } - if (!$routeLoader instanceof RouteLoaderInterface) { - throw new \LogicException(sprintf('Service "%s" must implement RouteLoaderInterface.', $resource)); + if (!method_exists($loaderObject, $method)) { + throw new \BadMethodCallException(sprintf('Method "%s" not found on "%s" when importing routing resource "%s"', $method, get_class($loaderObject), $resource)); } - $routeCollection = $routeLoader->getRouteCollection($this); + $routeCollection = call_user_func(array($loaderObject, $method), $this); + + if (!$routeCollection instanceof RouteCollection) { + $type = is_object($routeCollection) ? get_class($routeCollection) : gettype($routeCollection); + + throw new \LogicException(sprintf('The %s::%s method must return a RouteCollection: %s returned', get_class($loaderObject), $method, $type)); + } // make the service file tracked so that if it changes, the cache rebuilds - $this->addClassResource(new \ReflectionClass($routeLoader), $routeCollection); + $this->addClassResource(new \ReflectionClass($loaderObject), $routeCollection); return $routeCollection; } @@ -56,18 +86,6 @@ public function supports($resource, $type = null) return 'service' === $type; } - /** - * Returns a RouteLoaderInterface object matching the id. - * - * For example, if your application uses a service container, - * the $id may be a service id. - * - * @param string $id - * - * @return RouteLoaderInterface - */ - abstract protected function getRouteLoaderService($id); - private function addClassResource(\ReflectionClass $class, RouteCollection $collection) { do { diff --git a/src/Symfony/Component/Routing/Loader/RouteLoaderInterface.php b/src/Symfony/Component/Routing/Loader/RouteLoaderInterface.php deleted file mode 100644 index dd0af02d830e..000000000000 --- a/src/Symfony/Component/Routing/Loader/RouteLoaderInterface.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Symfony\Component\Config\Loader\LoaderInterface; -use Symfony\Component\Routing\RouteCollection; - -/** - * Defines a class that is able to load and return a RouteCollection. - * - * @author Ryan Weaver - */ -interface RouteLoaderInterface -{ - /** - * @param LoaderInterface $loader - * - * @return RouteCollection - */ - public function getRouteCollection(LoaderInterface $loader); -} diff --git a/src/Symfony/Component/Routing/Tests/Loader/ObjectRouteLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/ObjectRouteLoaderTest.php index a1439aa9a755..0fbd14fa0a00 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/ObjectRouteLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/ObjectRouteLoaderTest.php @@ -19,45 +19,89 @@ class ObjectRouteLoaderTest extends \PHPUnit_Framework_TestCase { public function testLoadCallsServiceAndReturnsCollection() { - $routeLoader = $this->getMock('Symfony\Component\Routing\Loader\RouteLoaderInterface'); - $serviceRouteLoader = new ObjectRouteLoaderForTest(); - - $serviceRouteLoader->loaderMap = array( - 'my_route_provider_service' => $routeLoader, - ); + $loader = new ObjectRouteLoaderForTest(); // create a basic collection that will be returned - $routes = new RouteCollection(); - $routes->add('foo', new Route('/foo')); + $collection = new RouteCollection(); + $collection->add('foo', new Route('/foo')); - $routeLoader - ->expects($this->any()) - ->method('getRouteCollection') - // the loader itself is passed - ->with($serviceRouteLoader) - ->will($this->returnValue($routes)); + // create some callable object + $service = $this->getMockBuilder('stdClass') + ->setMethods(array('loadRoutes')) + ->getMock(); + $service->expects($this->once()) + ->method('loadRoutes') + ->with($loader) + ->will($this->returnValue($collection)); - $actualRoutes = $serviceRouteLoader->load('my_route_provider_service', 'service'); + $loader->loaderMap = array( + 'my_route_provider_service' => $service, + ); - $this->assertSame($routes, $actualRoutes); + $actualRoutes = $loader->load( + 'my_route_provider_service:loadRoutes', + 'service' + ); + + $this->assertSame($collection, $actualRoutes); // the service file should be listed as a resource $this->assertNotEmpty($actualRoutes->getResources()); } /** - * @expectedException \LogicException + * @expectedException \InvalidArgumentException + * @dataProvider getBadResourceStrings */ - public function testExceptionOnInterfaceNotImplemented() + public function testExceptionWithoutSyntax($resourceString) { - // anything that doesn't implement the interface - $routeLoader = new \stdClass(); + $loader = new ObjectRouteLoaderForTest(); + $loader->load($resourceString); + } - $serviceRouteLoader = new ObjectRouteLoaderForTest(); - $serviceRouteLoader->loaderMap = array( - 'any_service_name' => $routeLoader, + public function getBadResourceStrings() + { + return array( + array('Foo'), + array('Bar::baz'), + array('Foo:Bar:baz'), ); + } + + /** + * @expectedException \LogicException + */ + public function testExceptionOnNoObjectReturned() + { + $loader = new ObjectRouteLoaderForTest(); + $loader->loaderMap = array('my_service' => 'NOT_AN_OBJECT'); + $loader->load('my_service:method'); + } + + /** + * @expectedException \BadMethodCallException + */ + public function testExceptionOnBadMethod() + { + $loader = new ObjectRouteLoaderForTest(); + $loader->loaderMap = array('my_service' => new \stdClass()); + $loader->load('my_service:method'); + } + + /** + * @expectedException \LogicException + */ + public function testExceptionOnMethodNotReturningCollection() + { + $service = $this->getMockBuilder('stdClass') + ->setMethods(array('loadRoutes')) + ->getMock(); + $service->expects($this->once()) + ->method('loadRoutes') + ->will($this->returnValue('NOT_A_COLLECTION')); - $serviceRouteLoader->load('any_service_name', 'service'); + $loader = new ObjectRouteLoaderForTest(); + $loader->loaderMap = array('my_service' => $service); + $loader->load('my_service:loadRoutes'); } } @@ -65,7 +109,7 @@ class ObjectRouteLoaderForTest extends ObjectRouteLoader { public $loaderMap = array(); - protected function getRouteLoaderService($id) + protected function getServiceObject($id) { return isset($this->loaderMap[$id]) ? $this->loaderMap[$id] : null; } From a4af474bc2d5690a2ed785f7b0ecf765a9572270 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Thu, 1 Oct 2015 14:34:46 -0400 Subject: [PATCH 17/18] updating CHANGELOG --- src/Symfony/Component/Routing/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Symfony/Component/Routing/CHANGELOG.md b/src/Symfony/Component/Routing/CHANGELOG.md index 864ef68dda82..7f5d9f0ec029 100644 --- a/src/Symfony/Component/Routing/CHANGELOG.md +++ b/src/Symfony/Component/Routing/CHANGELOG.md @@ -5,6 +5,8 @@ CHANGELOG ----- * allowed specifying a directory to recursively load all routing configuration files it contains + * Added ObjectRouteLoader and ServiceRouteLoader that allow routes to be loaded + by calling a method on an object/service. 2.5.0 ----- From a2cb79716a5a53bafb38c6e9cd79cab3ffc2530c Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Thu, 1 Oct 2015 15:26:23 -0400 Subject: [PATCH 18/18] Fixing missing gettype --- src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php b/src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php index 2a4203f06abd..9dfe85a65d05 100644 --- a/src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php +++ b/src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php @@ -55,7 +55,7 @@ public function load($resource, $type = null) $loaderObject = $this->getServiceObject($serviceString); if (!is_object($loaderObject)) { - throw new \LogicException(sprintf('%s:getServiceObject() must return an object: %s returned', get_class($this), $loaderObject)); + throw new \LogicException(sprintf('%s:getServiceObject() must return an object: %s returned', get_class($this), gettype($loaderObject))); } if (!method_exists($loaderObject, $method)) { pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy