diff --git a/.gitignore b/.gitignore index c089b095..c203cb3e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ phpunit.xml composer.lock /vendor/ +.phpunit.result.cache diff --git a/.travis.yml b/.travis.yml index 1b859d25..92619bc3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,6 @@ language: php php: - - 7.1 - 7.2 - 7.3 @@ -36,12 +35,12 @@ env: matrix: include: - - php: 7.1 - env: COMPOSER_FLAGS="--prefer-lowest" SYMFONY_REQUIRE=3.4.* SYMFONY_DEPRECATIONS_HELPER=weak - - php: 7.4 - env: SYMFONY_REQUIRE=4.3.* + - php: 7.2 + env: COMPOSER_FLAGS="--prefer-lowest" SYMFONY_REQUIRE=4.4.* SYMFONY_DEPRECATIONS_HELPER=weak - php: 7.4 env: SYMFONY_REQUIRE=4.4.* + - php: 7.4 + env: SYMFONY_REQUIRE=5.0.* fast_finish: true allow_failures: diff --git a/CHANGELOG.md b/CHANGELOG.md index 90ba4721..4aac044c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,27 @@ Changelog ========= +2.3.0 +----- + +* Dropped support for PHP 7.1 and Symfony 3.4 and 4.3. +* Added support for Symfony 5. +* Deprecated passing a route object (or anything else that is not a string) as + the `$name` parameter in the `generate` method of the ChainRouter and the + DynamicRouter. Symfony 5 enforces the `$name` parameter to be a string with + static type declaration. + The future proof way to generate a route from an object is to use the route + name `RouteObjectInterface::OBJECT_BASED_ROUTE_NAME` (`cmf_routing_object`) + and pass the route object in the parameters with key + `RouteObjectInterface::ROUTE_OBJECT` (`_route_object`). +* The VersatileGeneratorInterface::supports method is deprecated as it was used + to avoid errors with routers not supporting objects in `$name`. + +2.2.0 +----- + +* Avoid Symfony 4.3 event dispatcher deprecation warnings. + 2.1.1 ----- @@ -36,7 +57,7 @@ Released. --------- * **2016-11-30**: Changed file structure to have all php code in src/ - + 1.4.0 ----- diff --git a/composer.json b/composer.json index a3da702b..2e37d7c1 100644 --- a/composer.json +++ b/composer.json @@ -15,20 +15,20 @@ } ], "require": { - "php": "^7.1", - "symfony/routing": "^3.4 || ^4.3", - "symfony/http-kernel": "^3.4 || ^4.3", + "php": "^7.2", + "symfony/routing": "^4.4 || ^5.0", + "symfony/http-kernel": "^4.4 || ^5.0", "psr/log": "^1.0" }, "require-dev": { - "symfony/phpunit-bridge": "^4.2.2", - "symfony/dependency-injection": "^3.4 || ^4.3", - "symfony/config": "^3.4 || ^4.3", - "symfony/event-dispatcher": "^3.4 || ^4.3", + "symfony/phpunit-bridge": "^5.0", + "symfony/dependency-injection": "^4.4 || ^5.0", + "symfony/config": "^4.4 || ^5.0", + "symfony/event-dispatcher": "^4.4 || ^5.0", "symfony-cmf/testing": "^3@dev" }, "suggest": { - "symfony/event-dispatcher": "DynamicRouter can optionally trigger an event at the start of matching. Minimal version (^3.4 || ^4.3)" + "symfony/event-dispatcher": "DynamicRouter can optionally trigger an event at the start of matching. Minimal version (^4.4 || ^5.0)" }, "autoload": { "psr-4": { @@ -42,7 +42,7 @@ }, "extra": { "branch-alias": { - "dev-master": "2.2-dev" + "dev-master": "2.x-dev" } } } diff --git a/src/ChainRouter.php b/src/ChainRouter.php index 50dcca54..87b892d7 100644 --- a/src/ChainRouter.php +++ b/src/ChainRouter.php @@ -218,6 +218,10 @@ private function doMatch($pathinfo, Request $request = null) */ public function generate($name, $parameters = [], $absolute = UrlGeneratorInterface::ABSOLUTE_PATH) { + if (is_object($name)) { + @trigger_error('Passing an object as route name is deprecated since version 2.3 and will not work in Symfony 5.0. Pass the `RouteObjectInterface::OBJECT_BASED_ROUTE_NAME` as route name and the object in the parameters with key `RouteObjectInterface::ROUTE_OBJECT`.', E_USER_DEPRECATED); + } + $debug = []; foreach ($this->all() as $router) { diff --git a/src/ContentAwareGenerator.php b/src/ContentAwareGenerator.php index 05867b3f..d207c356 100644 --- a/src/ContentAwareGenerator.php +++ b/src/ContentAwareGenerator.php @@ -69,7 +69,15 @@ public function setContentRepository(ContentRepositoryInterface $contentReposito public function generate($name, $parameters = [], $absolute = UrlGeneratorInterface::ABSOLUTE_PATH) { if ($name instanceof SymfonyRoute) { + @trigger_error('Passing an object as route name is deprecated since version 2.3 and will not work in Symfony 5.0. Pass the `RouteObjectInterface::OBJECT_BASED_ROUTE_NAME` as route name and the object in the parameters with key `RouteObjectInterface::ROUTE_OBJECT`.', E_USER_DEPRECATED); + $route = $this->getBestLocaleRoute($name, $parameters); + } elseif (RouteObjectInterface::OBJECT_BASED_ROUTE_NAME === $name) { + if (array_key_exists(RouteObjectInterface::ROUTE_OBJECT, $parameters) && $parameters[RouteObjectInterface::ROUTE_OBJECT] instanceof SymfonyRoute) { + $route = $this->getBestLocaleRoute($parameters[RouteObjectInterface::ROUTE_OBJECT], $parameters); + } else { + $route = $this->getRouteByContent($name, $parameters); + } } elseif (is_string($name) && $name) { $route = $this->getRouteByName($name, $parameters); } else { @@ -164,7 +172,14 @@ protected function getBestLocaleRoute(SymfonyRoute $route, $parameters) protected function getRouteByContent($name, &$parameters) { if ($name instanceof RouteReferrersReadInterface) { + @trigger_error('Passing an object as route name is deprecated since version 2.3 and will not work in Symfony 5.0. Pass the `RouteObjectInterface::OBJECT_BASED_ROUTE_NAME` as route name and the object in the parameters with key `RouteObjectInterface::ROUTE_OBJECT`.', E_USER_DEPRECATED); + $content = $name; + } elseif (RouteObjectInterface::OBJECT_BASED_ROUTE_NAME === $name + && array_key_exists(RouteObjectInterface::ROUTE_OBJECT, $parameters) + && $parameters[RouteObjectInterface::ROUTE_OBJECT] instanceof RouteReferrersReadInterface + ) { + $content = $parameters[RouteObjectInterface::ROUTE_OBJECT]; } elseif (array_key_exists('content_id', $parameters) && null !== $this->contentRepository ) { @@ -290,10 +305,20 @@ public function supports($name) */ public function getRouteDebugMessage($name, array $parameters = []) { - if (!$name && array_key_exists('content_id', $parameters)) { + if ((!$name || RouteObjectInterface::OBJECT_BASED_ROUTE_NAME === $name) + && array_key_exists('content_id', $parameters) + ) { return 'Content id '.$parameters['content_id']; } + if (RouteObjectInterface::OBJECT_BASED_ROUTE_NAME === $name + && array_key_exists(RouteObjectInterface::ROUTE_OBJECT, $parameters) + && $parameters[RouteObjectInterface::ROUTE_OBJECT] instanceof RouteReferrersReadInterface + ) { + return 'Route aware content '.parent::getRouteDebugMessage($name, $parameters); + } + + // legacy if ($name instanceof RouteReferrersReadInterface) { return 'Route aware content '.parent::getRouteDebugMessage($name, $parameters); } diff --git a/src/DynamicRouter.php b/src/DynamicRouter.php index 38bc2b54..b96d5dbb 100644 --- a/src/DynamicRouter.php +++ b/src/DynamicRouter.php @@ -174,9 +174,13 @@ public function getGenerator() */ public function generate($name, $parameters = [], $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH) { + if (is_object($name)) { + @trigger_error('Passing an object as route name is deprecated since version 2.3 and will not work in Symfony 5.0. Pass the `RouteObjectInterface::OBJECT_BASED_ROUTE_NAME` as route name and the object in the parameters with key `RouteObjectInterface::ROUTE_OBJECT', E_USER_DEPRECATED); + } + if ($this->eventDispatcher) { $event = new RouterGenerateEvent($name, $parameters, $referenceType); - $this->eventDispatcher->dispatch(Events::PRE_DYNAMIC_GENERATE, $event); + $this->eventDispatcher->dispatch($event, Events::PRE_DYNAMIC_GENERATE); $name = $event->getRoute(); $parameters = $event->getParameters(); $referenceType = $event->getReferenceType(); @@ -225,7 +229,7 @@ public function match($pathinfo) $request = Request::create($pathinfo); if ($this->eventDispatcher) { $event = new RouterMatchEvent(); - $this->eventDispatcher->dispatch(Events::PRE_DYNAMIC_MATCH, $event); + $this->eventDispatcher->dispatch($event, Events::PRE_DYNAMIC_MATCH); } if (!empty($this->uriFilterRegexp) && !preg_match($this->uriFilterRegexp, $pathinfo)) { @@ -261,7 +265,7 @@ public function matchRequest(Request $request) { if ($this->eventDispatcher) { $event = new RouterMatchEvent($request); - $this->eventDispatcher->dispatch(Events::PRE_DYNAMIC_MATCH_REQUEST, $event); + $this->eventDispatcher->dispatch($event, Events::PRE_DYNAMIC_MATCH_REQUEST); } if ($this->uriFilterRegexp diff --git a/src/Event/RouterGenerateEvent.php b/src/Event/RouterGenerateEvent.php index c2ec15a1..c78b3061 100644 --- a/src/Event/RouterGenerateEvent.php +++ b/src/Event/RouterGenerateEvent.php @@ -11,8 +11,8 @@ namespace Symfony\Cmf\Component\Routing\Event; -use Symfony\Component\EventDispatcher\Event; use Symfony\Component\Routing\Route; +use Symfony\Contracts\EventDispatcher\Event; /** * Event fired before the dynamic router generates a url for a route. diff --git a/src/Event/RouterMatchEvent.php b/src/Event/RouterMatchEvent.php index cde16855..021352fe 100644 --- a/src/Event/RouterMatchEvent.php +++ b/src/Event/RouterMatchEvent.php @@ -11,8 +11,8 @@ namespace Symfony\Cmf\Component\Routing\Event; -use Symfony\Component\EventDispatcher\Event; use Symfony\Component\HttpFoundation\Request; +use Symfony\Contracts\EventDispatcher\Event; class RouterMatchEvent extends Event { diff --git a/src/ProviderBasedGenerator.php b/src/ProviderBasedGenerator.php index d4028c23..b850c7d2 100644 --- a/src/ProviderBasedGenerator.php +++ b/src/ProviderBasedGenerator.php @@ -77,10 +77,30 @@ public function supports($name) */ public function getRouteDebugMessage($name, array $parameters = []) { + if (RouteObjectInterface::OBJECT_BASED_ROUTE_NAME === $name + && array_key_exists(RouteObjectInterface::ROUTE_OBJECT, $parameters) + ) { + $routeObject = $parameters[RouteObjectInterface::ROUTE_OBJECT]; + if ($routeObject instanceof RouteObjectInterface) { + return 'Route with key '.$routeObject->getRouteKey(); + } + + if ($routeObject instanceof SymfonyRoute) { + return 'Route with path '.$routeObject->getPath(); + } + + if (is_object($routeObject)) { + return get_class($routeObject); + } + + return 'Null route'; + } + if (is_scalar($name)) { return $name; } + // legacy if (is_array($name)) { return serialize($name); } diff --git a/src/RouteObjectInterface.php b/src/RouteObjectInterface.php index 51b3d698..6e66af68 100644 --- a/src/RouteObjectInterface.php +++ b/src/RouteObjectInterface.php @@ -56,6 +56,11 @@ interface RouteObjectInterface */ const CONTENT_ID = '_content_id'; + /** + * Route name used when passing a route object to the generator in $parameters[RouteObjectInterface::ROUTE_OBJECT]. + */ + const OBJECT_BASED_ROUTE_NAME = 'cmf_routing_object'; + /** * Get the content document this route entry stands for. If non-null, * the ControllerClassMapper uses it to identify a controller and diff --git a/src/VersatileGeneratorInterface.php b/src/VersatileGeneratorInterface.php index ca77bf1b..66fa368f 100644 --- a/src/VersatileGeneratorInterface.php +++ b/src/VersatileGeneratorInterface.php @@ -14,8 +14,7 @@ use Symfony\Component\Routing\Generator\UrlGeneratorInterface; /** - * This generator is able to handle more than string route names as symfony - * core supports them. + * This generator can provide additional information about the route that we wanted to generate. */ interface VersatileGeneratorInterface extends UrlGeneratorInterface { @@ -26,6 +25,13 @@ interface VersatileGeneratorInterface extends UrlGeneratorInterface * resolved to a route, only whether the router can generate routes from * objects of this class. * + * @deprecated This method is deprecated since version 2.3 and will be + * removed in version 3.O. + * + * This method was used to not call generators that can not handle objects + * in $name. With Symfony 5, this becomes obsolete as the strict type + * declaration prevents passing anything else than a string as $name. + * * @param mixed $name The route "name" which may also be an object or anything * * @return bool @@ -36,9 +42,8 @@ public function supports($name); * Convert a route identifier (name, content object etc) into a string * usable for logging and other debug/error messages. * - * @param mixed $name - * @param array $parameters which should contain a content field containing - * a RouteReferrersReadInterface object + * @param mixed $name In Symfony 5, the name can only be a string + * @param array $parameters Which might hold a route object or content id or similar to include in the debug message * * @return string */ diff --git a/tests/Unit/Routing/ChainRouterTest.php b/tests/Unit/Routing/ChainRouterTest.php index e36f501d..cf60fd97 100644 --- a/tests/Unit/Routing/ChainRouterTest.php +++ b/tests/Unit/Routing/ChainRouterTest.php @@ -15,6 +15,7 @@ use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; use Symfony\Cmf\Component\Routing\ChainRouter; +use Symfony\Cmf\Component\Routing\RouteObjectInterface; use Symfony\Cmf\Component\Routing\VersatileGeneratorInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface; @@ -22,6 +23,7 @@ use Symfony\Component\Routing\Exception\ResourceNotFoundException; use Symfony\Component\Routing\Exception\RouteNotFoundException; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Symfony\Component\Routing\Loader\ObjectRouteLoader; use Symfony\Component\Routing\Matcher\RequestMatcherInterface; use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\Route; @@ -613,9 +615,16 @@ public function testGenerateNotFound() /** * Route is an object but no versatile generator around to do the debug message. + * + * @group legacy + * @expectedDeprecation Passing an object as route name is deprecated since version 2.3 and will not work in Symfony 5.0. Pass the `RouteObjectInterface::OBJECT_BASED_ROUTE_NAME` as route name and the object in the parameters with key `RouteObjectInterface::ROUTE_OBJECT`. */ public function testGenerateObjectNotFound() { + if (!class_exists(ObjectRouteLoader::class)) { + $this->markTestSkipped('Symfony 5 would throw a TypeError.'); + } + $name = new \stdClass(); $parameters = ['test' => 'value']; @@ -634,9 +643,16 @@ public function testGenerateObjectNotFound() /** * A versatile router will generate the debug message. + * + * @group legacy + * @expectedDeprecation Passing an object as route name is deprecated since version 2.3 and will not work in Symfony 5.0. Pass the `RouteObjectInterface::OBJECT_BASED_ROUTE_NAME` as route name and the object in the parameters with key `RouteObjectInterface::ROUTE_OBJECT`. */ public function testGenerateObjectNotFoundVersatile() { + if (!class_exists(ObjectRouteLoader::class)) { + $this->markTestSkipped('Symfony 5 would throw a TypeError.'); + } + $name = new \stdClass(); $parameters = ['test' => 'value']; @@ -663,8 +679,16 @@ public function testGenerateObjectNotFoundVersatile() $this->router->generate($name, $parameters); } + /** + * @group legacy + * @expectedDeprecation Passing an object as route name is deprecated since version 2.3 and will not work in Symfony 5.0. Pass the `RouteObjectInterface::OBJECT_BASED_ROUTE_NAME` as route name and the object in the parameters with key `RouteObjectInterface::ROUTE_OBJECT`. + */ public function testGenerateObjectName() { + if (!class_exists(ObjectRouteLoader::class)) { + $this->markTestSkipped('Symfony 5 would throw a TypeError.'); + } + $name = new \stdClass(); $parameters = ['test' => 'value']; @@ -694,6 +718,57 @@ public function testGenerateObjectName() $this->assertEquals($name, $result); } + /** + * This test currently triggers a deprecation notice because of ChainRouter BC. + */ + public function testGenerateWithObjectNameInParametersNotFoundVersatile() + { + $name = RouteObjectInterface::OBJECT_BASED_ROUTE_NAME; + $parameters = ['test' => 'value', '_route_object' => new \stdClass()]; + + $chainedRouter = $this->createMock(VersatileRouter::class); + $chainedRouter + ->expects($this->once()) + ->method('supports') + ->willReturn(true) + ; + $chainedRouter->expects($this->once()) + ->method('generate') + ->with($name, $parameters, UrlGeneratorInterface::ABSOLUTE_PATH) + ->will($this->throwException(new RouteNotFoundException())) + ; + $chainedRouter->expects($this->once()) + ->method('getRouteDebugMessage') + ->with($name, $parameters) + ->willReturn('message') + ; + + $this->router->add($chainedRouter, 10); + + $this->expectException(RouteNotFoundException::class); + $this->router->generate($name, $parameters); + } + + public function testGenerateWithObjectNameInParameters() + { + $name = RouteObjectInterface::OBJECT_BASED_ROUTE_NAME; + $parameters = ['test' => 'value', '_route_object' => new \stdClass()]; + + $defaultRouter = $this->createMock(RouterInterface::class); + + $defaultRouter + ->expects($this->once()) + ->method('generate') + ->with($name, $parameters, UrlGeneratorInterface::ABSOLUTE_PATH) + ->willReturn('/foo/bar') + ; + + $this->router->add($defaultRouter, 200); + + $result = $this->router->generate($name, $parameters); + $this->assertEquals('/foo/bar', $result); + } + public function testWarmup() { $dir = 'test_dir'; @@ -745,6 +820,9 @@ public function testRouteCollection() $this->assertEquals(['high', 'low'], $names); } + /** + * @group legacy + */ public function testSupport() { $router = $this->createMock(VersatileRouter::class); diff --git a/tests/Unit/Routing/ContentAwareGeneratorTest.php b/tests/Unit/Routing/ContentAwareGeneratorTest.php index a3b54aec..447a7a97 100644 --- a/tests/Unit/Routing/ContentAwareGeneratorTest.php +++ b/tests/Unit/Routing/ContentAwareGeneratorTest.php @@ -15,11 +15,13 @@ use PHPUnit\Framework\TestCase; use Symfony\Cmf\Component\Routing\ContentAwareGenerator; use Symfony\Cmf\Component\Routing\ContentRepositoryInterface; +use Symfony\Cmf\Component\Routing\RouteObjectInterface; use Symfony\Cmf\Component\Routing\RouteProviderInterface; use Symfony\Cmf\Component\Routing\RouteReferrersReadInterface; use Symfony\Cmf\Component\Routing\Tests\Unit\Routing\RouteMock; use Symfony\Component\Routing\CompiledRoute; use Symfony\Component\Routing\Exception\RouteNotFoundException; +use Symfony\Component\Routing\Loader\ObjectRouteLoader; use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\Route; @@ -70,8 +72,16 @@ public function setUp() $this->generator = new TestableContentAwareGenerator($this->provider); } + /** + * @group legacy + * @expectedDeprecation Passing an object as route name is deprecated since version 2.3 and will not work in Symfony 5.0. Pass the `RouteObjectInterface::OBJECT_BASED_ROUTE_NAME` as route name and the object in the parameters with key `RouteObjectInterface::ROUTE_OBJECT`. + */ public function testGenerateFromContent() { + if (!class_exists(ObjectRouteLoader::class)) { + $this->markTestSkipped('Symfony 5 would throw a TypeError.'); + } + $this->provider->expects($this->never()) ->method('getRouteByName') ; @@ -87,7 +97,20 @@ public function testGenerateFromContent() $this->assertEquals('result_url', $this->generator->generate($this->contentDocument)); } - public function testGenerateFromContentId() + public function testGenerateFromContentInParameters() + { + $this->provider->expects($this->never()) + ->method('getRouteByName') + ; + $this->routeDocument->expects($this->once()) + ->method('compile') + ->willReturn($this->routeCompiled) + ; + + $this->assertEquals('result_url', $this->generator->generate(RouteObjectInterface::OBJECT_BASED_ROUTE_NAME, [RouteObjectInterface::ROUTE_OBJECT => $this->routeDocument])); + } + + public function testGenerateFromContentIdEmptyRouteName() { $this->provider->expects($this->never()) ->method('getRouteByName') @@ -114,6 +137,34 @@ public function testGenerateFromContentId() $this->assertEquals('result_url', $this->generator->generate('', ['content_id' => '/content/id'])); } + public function testGenerateFromContentId() + { + $this->provider->expects($this->never()) + ->method('getRouteByName') + ; + + $contentRepository = $this->createMock(ContentRepositoryInterface::class); + $contentRepository->expects($this->once()) + ->method('findById') + ->with('/content/id') + ->will($this->returnValue($this->contentDocument)) + ; + $this->generator->setContentRepository($contentRepository); + + $this->contentDocument->expects($this->once()) + ->method('getRoutes') + ->will($this->returnValue([$this->routeDocument])) + ; + + $this->routeDocument->expects($this->once()) + ->method('compile') + ->will($this->returnValue($this->routeCompiled)) + ; + + $generated = $this->generator->generate(RouteObjectInterface::OBJECT_BASED_ROUTE_NAME, ['content_id' => '/content/id']); + $this->assertEquals('result_url', $generated); + } + public function testGenerateEmptyRouteString() { $this->provider->expects($this->never()) @@ -130,7 +181,8 @@ public function testGenerateEmptyRouteString() ->will($this->returnValue($this->routeCompiled)) ; - $this->assertEquals('result_url', $this->generator->generate($this->contentDocument)); + $generated = $this->generator->generate(RouteObjectInterface::OBJECT_BASED_ROUTE_NAME, [RouteObjectInterface::ROUTE_OBJECT => $this->contentDocument]); + $this->assertEquals('result_url', $generated); } public function testGenerateRouteMultilang() @@ -160,7 +212,8 @@ public function testGenerateRouteMultilang() ->will($this->returnValue($this->routeCompiled)) ; - $this->assertEquals('result_url', $this->generator->generate($route_en, ['_locale' => 'de'])); + $generated = $this->generator->generate(RouteObjectInterface::OBJECT_BASED_ROUTE_NAME, ['_locale' => 'de', RouteObjectInterface::ROUTE_OBJECT => $route_en]); + $this->assertEquals('result_url', $generated); } public function testGenerateRouteMultilangDefaultLocale() @@ -185,7 +238,8 @@ public function testGenerateRouteMultilangDefaultLocale() ->will($this->returnValue([])) ; - $this->assertEquals('result_url', $this->generator->generate($route, ['_locale' => 'en'])); + $generated = $this->generator->generate(RouteObjectInterface::OBJECT_BASED_ROUTE_NAME, ['_locale' => 'en', RouteObjectInterface::ROUTE_OBJECT => $route]); + $this->assertEquals('result_url', $generated); } public function testGenerateRouteMultilangLocaleNomatch() @@ -214,7 +268,8 @@ public function testGenerateRouteMultilangLocaleNomatch() ->method('compile') ; - $this->assertEquals('result_url', $this->generator->generate($route_en, ['_locale' => 'fr'])); + $generated = $this->generator->generate(RouteObjectInterface::OBJECT_BASED_ROUTE_NAME, ['_locale' => 'fr', RouteObjectInterface::ROUTE_OBJECT => $route_en]); + $this->assertEquals('result_url', $generated); } public function testGenerateNoncmfRouteMultilang() @@ -226,7 +281,8 @@ public function testGenerateNoncmfRouteMultilang() ->will($this->returnValue($this->routeCompiled)) ; - $this->assertEquals('result_url', $this->generator->generate($route_en, ['_locale' => 'de'])); + $generated = $this->generator->generate(RouteObjectInterface::OBJECT_BASED_ROUTE_NAME, ['_locale' => 'de', RouteObjectInterface::ROUTE_OBJECT => $route_en]); + $this->assertEquals('result_url', $generated); } public function testGenerateRoutenameMultilang() @@ -300,7 +356,8 @@ public function testGenerateDocumentMultilang() ->will($this->returnValue($this->routeCompiled)) ; - $this->assertEquals('result_url', $this->generator->generate($this->contentDocument, ['_locale' => 'de'])); + $generated = $this->generator->generate(RouteObjectInterface::OBJECT_BASED_ROUTE_NAME, ['_locale' => 'de', RouteObjectInterface::ROUTE_OBJECT => $this->contentDocument]); + $this->assertEquals('result_url', $generated); } public function testGenerateDocumentMultilangLocaleNomatch() @@ -322,7 +379,8 @@ public function testGenerateDocumentMultilangLocaleNomatch() ->method('compile') ; - $this->assertEquals('result_url', $this->generator->generate($this->contentDocument, ['_locale' => 'fr'])); + $generated = $this->generator->generate(RouteObjectInterface::OBJECT_BASED_ROUTE_NAME, ['_locale' => 'fr', RouteObjectInterface::ROUTE_OBJECT => $this->contentDocument]); + $this->assertEquals('result_url', $generated); } /** @@ -339,6 +397,21 @@ public function testGenerateNoContent() */ public function testGenerateInvalidContent() { + $this->expectException(RouteNotFoundException::class); + $this->generator->generate(RouteObjectInterface::OBJECT_BASED_ROUTE_NAME, [RouteObjectInterface::ROUTE_OBJECT => $this]); + } + + /** + * Generate with an object that is neither a route nor route aware. + * + * @group legacy + */ + public function testGenerateInvalidContentLegacy() + { + if (!class_exists(ObjectRouteLoader::class)) { + $this->markTestSkipped('Symfony 5 would throw a TypeError.'); + } + $this->expectException(RouteNotFoundException::class); $this->generator->generate($this); } @@ -408,7 +481,7 @@ public function testGenerateNoRoutes() ->will($this->returnValue([])); $this->expectException(RouteNotFoundException::class); - $this->generator->generate($this->contentDocument); + $this->generator->generate(RouteObjectInterface::OBJECT_BASED_ROUTE_NAME, [RouteObjectInterface::ROUTE_OBJECT => $this->contentDocument]); } /** @@ -421,7 +494,7 @@ public function testGenerateInvalidRoute() ->will($this->returnValue([$this])); $this->expectException(RouteNotFoundException::class); - $this->generator->generate($this->contentDocument); + $this->generator->generate(RouteObjectInterface::OBJECT_BASED_ROUTE_NAME, [RouteObjectInterface::ROUTE_OBJECT => $this->contentDocument]); } public function testGetLocaleAttribute() @@ -450,6 +523,9 @@ public function testGetLocaleContext() $this->assertEquals('de', $this->generator->getLocale($attributes)); } + /** + * @group legacy + */ public function testSupports() { $this->assertTrue($this->generator->supports('')); @@ -459,6 +535,16 @@ public function testSupports() } public function testGetRouteDebugMessage() + { + $this->assertContains('/some/content', $this->generator->getRouteDebugMessage(RouteObjectInterface::OBJECT_BASED_ROUTE_NAME, ['content_id' => '/some/content'])); + $this->assertContains('Route aware content Symfony\Cmf\Component\Routing\Tests\Routing\RouteAware', $this->generator->getRouteDebugMessage(RouteObjectInterface::OBJECT_BASED_ROUTE_NAME, [RouteObjectInterface::ROUTE_OBJECT => new RouteAware()])); + $this->assertContains('/some/content', $this->generator->getRouteDebugMessage('/some/content')); + } + + /** + * @legacy + */ + public function testGetRouteDebugMessageLegacy() { $this->assertContains('/some/content', $this->generator->getRouteDebugMessage(null, ['content_id' => '/some/content'])); $this->assertContains('Route aware content Symfony\Cmf\Component\Routing\Tests\Routing\RouteAware', $this->generator->getRouteDebugMessage(new RouteAware())); diff --git a/tests/Unit/Routing/DynamicRouterTest.php b/tests/Unit/Routing/DynamicRouterTest.php index 828d1368..02aa03a2 100644 --- a/tests/Unit/Routing/DynamicRouterTest.php +++ b/tests/Unit/Routing/DynamicRouterTest.php @@ -138,6 +138,9 @@ public function testGenerate() $this->assertEquals('http://test', $url); } + /** + * @group legacy + */ public function testSupports() { $name = 'foo/bar'; @@ -338,7 +341,7 @@ public function testEventHandler() $eventDispatcher->expects($this->once()) ->method('dispatch') - ->with(Events::PRE_DYNAMIC_MATCH, $this->equalTo(new RouterMatchEvent())) + ->with($this->equalTo(new RouterMatchEvent()), Events::PRE_DYNAMIC_MATCH) ; $routeDefaults = ['foo' => 'bar']; @@ -359,12 +362,12 @@ public function testEventHandlerRequest() $that = $this; $eventDispatcher->expects($this->once()) ->method('dispatch') - ->with(Events::PRE_DYNAMIC_MATCH_REQUEST, $this->callback(function ($event) use ($that) { + ->with($this->callback(function ($event) use ($that) { $that->assertInstanceOf(RouterMatchEvent::class, $event); $that->assertEquals($that->request, $event->getRequest()); return true; - })) + }), Events::PRE_DYNAMIC_MATCH_REQUEST) ; $routeDefaults = ['foo' => 'bar']; @@ -392,7 +395,7 @@ public function testEventHandlerGenerate() $that = $this; $eventDispatcher->expects($this->once()) ->method('dispatch') - ->with(Events::PRE_DYNAMIC_GENERATE, $this->callback(function ($event) use ($that, $oldname, $newname, $oldparameters, $newparameters, $oldReferenceType, $newReferenceType) { + ->with($this->callback(function ($event) use ($that, $oldname, $newname, $oldparameters, $newparameters, $oldReferenceType, $newReferenceType) { $that->assertInstanceOf(RouterGenerateEvent::class, $event); if (empty($that->seen)) { // phpunit is calling the callback twice, and because we update the event the second time fails @@ -408,7 +411,7 @@ public function testEventHandlerGenerate() $event->setReferenceType($newReferenceType); return true; - })) + }), Events::PRE_DYNAMIC_GENERATE) ; $this->generator->expects($this->once())