From 0623e9ab0b6ae01db0047471314a42be100e92e8 Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Tue, 10 Feb 2026 10:25:51 +0100 Subject: [PATCH] Provide PHP routing files in parallel of the XML ones Symfony has deprecated the XML format for route definitions. The bundle now ships PHP routing files in addition to the XML ones (with tests ensuring they are in sync) and the documentation uses the PHP files. The XML files will be removed in the next major version of the bundle as removing them is a BC break. --- docs/index.rst | 4 +- docs/routing.rst | 22 +++--- src/Resources/config/routing/all.php | 28 +++++++ .../config/routing/change_password.php | 18 +++++ src/Resources/config/routing/profile.php | 22 ++++++ src/Resources/config/routing/registration.php | 30 ++++++++ src/Resources/config/routing/resetting.php | 30 ++++++++ src/Resources/config/routing/security.php | 26 +++++++ tests/Routing/RoutingTest.php | 74 ++++++++++++++++++- 9 files changed, 240 insertions(+), 14 deletions(-) create mode 100644 src/Resources/config/routing/all.php create mode 100644 src/Resources/config/routing/change_password.php create mode 100644 src/Resources/config/routing/profile.php create mode 100644 src/Resources/config/routing/registration.php create mode 100644 src/Resources/config/routing/resetting.php create mode 100644 src/Resources/config/routing/security.php diff --git a/docs/index.rst b/docs/index.rst index d317c4432..85d3eab9a 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -360,12 +360,12 @@ logging in, creating users, etc. # app/config/routing.yml fos_user: - resource: "@FOSUserBundle/Resources/config/routing/all.xml" + resource: "@FOSUserBundle/Resources/config/routing/all.php" .. code-block:: xml - + .. note:: diff --git a/docs/routing.rst b/docs/routing.rst index c80668c97..8443a43e3 100644 --- a/docs/routing.rst +++ b/docs/routing.rst @@ -1,7 +1,7 @@ Advanced routing configuration ============================== -By default, the routing file ``@FOSUserBundle/Resources/config/routing/all.xml`` imports +By default, the routing file ``@FOSUserBundle/Resources/config/routing/all.php`` imports all the routing files and enables all the routes. In the case you want to enable or disable the different available routes, just use the single routing configuration files. @@ -12,29 +12,29 @@ single routing configuration files. # app/config/routing.yml fos_user_security: - resource: "@FOSUserBundle/Resources/config/routing/security.xml" + resource: "@FOSUserBundle/Resources/config/routing/security.php" fos_user_profile: - resource: "@FOSUserBundle/Resources/config/routing/profile.xml" + resource: "@FOSUserBundle/Resources/config/routing/profile.php" prefix: /profile fos_user_register: - resource: "@FOSUserBundle/Resources/config/routing/registration.xml" + resource: "@FOSUserBundle/Resources/config/routing/registration.php" prefix: /register fos_user_resetting: - resource: "@FOSUserBundle/Resources/config/routing/resetting.xml" + resource: "@FOSUserBundle/Resources/config/routing/resetting.php" prefix: /resetting fos_user_change_password: - resource: "@FOSUserBundle/Resources/config/routing/change_password.xml" + resource: "@FOSUserBundle/Resources/config/routing/change_password.php" prefix: /profile .. code-block:: xml - - - - - + + + + + diff --git a/src/Resources/config/routing/all.php b/src/Resources/config/routing/all.php new file mode 100644 index 000000000..04ff6b68d --- /dev/null +++ b/src/Resources/config/routing/all.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader\Configurator; + +return static function (RoutingConfigurator $routes): void { + $routes->import('@FOSUserBundle/Resources/config/routing/security.php'); + + $routes->import('@FOSUserBundle/Resources/config/profile.php') + ->prefix('/profile'); + + $routes->import('@FOSUserBundle/Resources/config/registration.php') + ->prefix('/register'); + + $routes->import('@FOSUserBundle/Resources/config/resetting.php') + ->prefix('/resetting'); + + $routes->import('@FOSUserBundle/Resources/config/change_password.php') + ->prefix('/profile'); +}; diff --git a/src/Resources/config/routing/change_password.php b/src/Resources/config/routing/change_password.php new file mode 100644 index 000000000..9d5813887 --- /dev/null +++ b/src/Resources/config/routing/change_password.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader\Configurator; + +return static function (RoutingConfigurator $routes): void { + $routes->add('fos_user_change_password', '/change-password') + ->methods(['GET', 'POST']) + ->controller('fos_user.change_password.controller::changePasswordAction'); +}; diff --git a/src/Resources/config/routing/profile.php b/src/Resources/config/routing/profile.php new file mode 100644 index 000000000..2c18daf71 --- /dev/null +++ b/src/Resources/config/routing/profile.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader\Configurator; + +return static function (RoutingConfigurator $routes): void { + $routes->add('fos_user_profile_show', '/') + ->methods(['GET']) + ->controller('fos_user.profile.controller::showAction'); + + $routes->add('fos_user_profile_edit', '/edit') + ->methods(['GET', 'POST']) + ->controller('fos_user.profile.controller::editAction'); +}; diff --git a/src/Resources/config/routing/registration.php b/src/Resources/config/routing/registration.php new file mode 100644 index 000000000..4c5df33d4 --- /dev/null +++ b/src/Resources/config/routing/registration.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader\Configurator; + +return static function (RoutingConfigurator $routes): void { + $routes->add('fos_user_registration_register', '/') + ->methods(['GET', 'POST']) + ->controller('fos_user.registration.controller::registerAction'); + + $routes->add('fos_user_registration_check_email', '/check-email') + ->methods(['GET']) + ->controller('fos_user.registration.controller::checkEmailAction'); + + $routes->add('fos_user_registration_confirm', '/confirm/{token}') + ->methods(['GET']) + ->controller('fos_user.registration.controller::confirmAction'); + + $routes->add('fos_user_registration_confirmed', '/confirmed') + ->methods(['GET']) + ->controller('fos_user.registration.controller::confirmedAction'); +}; diff --git a/src/Resources/config/routing/resetting.php b/src/Resources/config/routing/resetting.php new file mode 100644 index 000000000..01e54dd32 --- /dev/null +++ b/src/Resources/config/routing/resetting.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader\Configurator; + +return static function (RoutingConfigurator $routes): void { + $routes->add('fos_user_resetting_request', '/request') + ->methods(['GET']) + ->controller('fos_user.resetting.controller::requestAction'); + + $routes->add('fos_user_resetting_send_email', '/send-email') + ->methods(['POST']) + ->controller('fos_user.resetting.controller::sendEmailAction'); + + $routes->add('fos_user_resetting_check_email', '/check-email') + ->methods(['GET']) + ->controller('fos_user.resetting.controller::checkEmailAction'); + + $routes->add('fos_user_resetting_reset', '/reset/{token}') + ->methods(['GET', 'POST']) + ->controller('fos_user.resetting.controller::resetAction'); +}; diff --git a/src/Resources/config/routing/security.php b/src/Resources/config/routing/security.php new file mode 100644 index 000000000..4f220ed57 --- /dev/null +++ b/src/Resources/config/routing/security.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader\Configurator; + +return static function (RoutingConfigurator $routes): void { + $routes->add('fos_user_security_login', '/login') + ->methods(['GET', 'POST']) + ->controller('fos_user.security.controller::loginAction'); + + $routes->add('fos_user_security_check', '/login_check') + ->methods(['POST']) + ->controller('fos_user.security.controller::checkAction'); + + $routes->add('fos_user_security_logout', '/logout') + ->methods(['GET', 'POST']) + ->controller('fos_user.security.controller::logoutAction'); +}; diff --git a/tests/Routing/RoutingTest.php b/tests/Routing/RoutingTest.php index 0427ce2aa..bc0815b1e 100644 --- a/tests/Routing/RoutingTest.php +++ b/tests/Routing/RoutingTest.php @@ -13,6 +13,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Config\FileLocator; +use Symfony\Component\Routing\Loader\PhpFileLoader; use Symfony\Component\Routing\Loader\XmlFileLoader; use Symfony\Component\Routing\RouteCollection; @@ -27,6 +28,43 @@ class RoutingTest extends TestCase */ public function testLoadRouting($routeName, $path, array $methods) { + $locator = new FileLocator(); + $loader = new PhpFileLoader($locator); + + $collection = new RouteCollection(); + $collection->addCollection($loader->load(__DIR__.'/../../src/Resources/config/routing/change_password.php')); + $subCollection = $loader->load(__DIR__.'/../../src/Resources/config/routing/profile.php'); + $subCollection->addPrefix('/profile'); + $collection->addCollection($subCollection); + $subCollection = $loader->load(__DIR__.'/../../src/Resources/config/routing/registration.php'); + $subCollection->addPrefix('/register'); + $collection->addCollection($subCollection); + $subCollection = $loader->load(__DIR__.'/../../src/Resources/config/routing/resetting.php'); + $subCollection->addPrefix('/resetting'); + $collection->addCollection($subCollection); + $collection->addCollection($loader->load(__DIR__.'/../../src/Resources/config/routing/security.php')); + + $route = $collection->get($routeName); + $this->assertNotNull($route, sprintf('The route "%s" should exists', $routeName)); + $this->assertSame($path, $route->getPath()); + $this->assertSame($methods, $route->getMethods()); + } + + /** + * @dataProvider loadRoutingProvider + * + * @group legacy + * + * @param string $routeName + * @param string $path + * @param string[] $methods + */ + public function testLoadRoutingLegacy($routeName, $path, array $methods) + { + if (!class_exists(XmlFileLoader::class)) { + $this->markTestSkipped('XML routing files are not supported on Symfony 8.'); + } + $locator = new FileLocator(); $loader = new XmlFileLoader($locator); @@ -52,7 +90,7 @@ public function testLoadRouting($routeName, $path, array $methods) /** * @return iterable */ - public function loadRoutingProvider(): iterable + public static function loadRoutingProvider(): iterable { return [ ['fos_user_change_password', '/change-password', ['GET', 'POST']], @@ -75,4 +113,38 @@ public function loadRoutingProvider(): iterable ['fos_user_security_logout', '/logout', ['GET', 'POST']], ]; } + + /** + * @dataProvider provideRouteFiles + * + * @group legacy + */ + public function testLegacyFileConsistency(string $filename): void + { + if (!class_exists(XmlFileLoader::class)) { + $this->markTestSkipped('XML routing files are not supported on Symfony 8.'); + } + + $locator = new FileLocator(); + + $phpLoader = new PhpFileLoader($locator); + $xmlLoader = new XmlFileLoader($locator); + + $phpCollection = $phpLoader->load(__DIR__.\sprintf('/../../src/Resources/config/routing/%s.php', $filename)); + $xmlCollection = $xmlLoader->load(__DIR__.\sprintf('/../../src/Resources/config/routing/%s.xml', $filename)); + + $this->assertEquals($phpCollection->all(), $xmlCollection->all()); + } + + /** + * @return iterable + */ + public static function provideRouteFiles(): iterable + { + yield ['profile']; + yield ['registration']; + yield ['resetting']; + yield ['security']; + } } +// @php-cs-fixer-ignore php_unit_strict We intentionally use a non-strict comparison to verify that loaded routes are equivalent in the consistency test.