diff --git a/core/lib/Drupal/Core/Routing/UrlGenerator.php b/core/lib/Drupal/Core/Routing/UrlGenerator.php new file mode 100644 index 0000000..5aa3d7a --- /dev/null +++ b/core/lib/Drupal/Core/Routing/UrlGenerator.php @@ -0,0 +1,48 @@ +connection = $connection; + $this->context = $context; + $this->table = $table; + } + + /** + * Generates a URL from the given parameters. + */ + public function generate($name, $parameters = array(), $absolute = false) { + $result = $this->connection->query('select route from {' . $this->table . '} where name = :name', array(':name' => $name)); + $row = $result->fetchObject(); + + if (empty($row)) { + throw new RouteNotFoundException(sprintf('Route "%s" does not exist.', $name)); + } + + $route = unserialize($row->route); + + // We cannot know if and what compiler class is set in the route coming from + // the database. To make Symfony's URL generation code work we have to set + // it here explicitly. + // See http://drupal.org/node/1705488#comment-6645232 + $route->setOption('compiler_class', '\Symfony\Component\Routing\RouteCompiler'); + + $compiledRoute = $route->compile(); + + return $this->doGenerate($compiledRoute->getVariables(), $route->getDefaults(), $route->getRequirements(), $compiledRoute->getTokens(), $parameters, $name, $absolute); + } +} diff --git a/core/modules/system/lib/Drupal/system/Tests/Routing/UrlGeneratorTest.php b/core/modules/system/lib/Drupal/system/Tests/Routing/UrlGeneratorTest.php new file mode 100644 index 0000000..661d8f5 --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Tests/Routing/UrlGeneratorTest.php @@ -0,0 +1,146 @@ + 'URL generator tests', + 'description' => 'Confirm that the url generation code is working correctly.', + 'group' => 'Routing', + ); + } + + function __construct($test_id = NULL) { + parent::__construct($test_id); + + $this->fixtures = new RoutingFixtures(); + + $this->requests = array( + Request::create('http://test.com/foo?bar=baz'), + Request::create('https://test.com/foo?bar=baz'), + Request::create('test.com:90/foo'), + Request::create('https://test.com:90/foo'), + Request::create('https://127.0.0.1:90/foo'), + Request::create('https://[::1]:90/foo'), + Request::create('http://example.com/jsonrpc', 'POST', array(), array(), array(), array(), '{"jsonrpc":"2.0","method":"echo","id":7,"params":["Hello World"]}'), + Request::create('http://test.com'), + Request::create('http://test.com:90/?test=1'), + Request::create('http://test:test@test.com'), + ); + } + + public function tearDown() { + $this->fixtures->dropTables(Database::getConnection()); + + parent::tearDown(); + } + + function testSampleUrlGeneration() { + $connection = Database::getConnection(); + $this->fixtures->createTables($connection); + + $dumper = new MatcherDumper($connection, 'test_routes'); + $sampleRoutes = $this->fixtures->sampleRouteCollection(); + $dumper->addRoutes($sampleRoutes); + $dumper->dump(); + + foreach ($this->requests as $request) { + $context = new RequestContext(); + $context->fromRequest($request); + $generator = new UrlGenerator(Database::getConnection(), $context, "test_routes"); + + foreach ($sampleRoutes->all() as $name => $route) { + $url = $generator->generate($name); + $this->assertEqual($route->getPattern(), $url, "Correct path generated for route $name."); + } + } + } + + /** + * Confirms correct URL generation for a more complex RouteCollection + */ + function testComplexUrlGeneration() { + $connection = Database::getConnection(); + $this->fixtures->createTables($connection); + + $dumper = new MatcherDumper($connection, 'test_routes'); + $sampleRoutes = $this->fixtures->complexRouteCollection(); + $dumper->addRoutes($sampleRoutes); + $dumper->dump(); + + $sampleArgs = array('foo', 'bar', 'baz'); + + foreach ($this->requests as $request) { + $context = new RequestContext(); + $context->fromRequest($request); + $generator = new UrlGenerator(Database::getConnection(), $context, "test_routes"); + + foreach ($sampleRoutes->all() as $name => $route) { + $pattern = $route->getPattern(); + + //constructing the expected URL by pattern matching + $expected_url = $pattern; + $parameters = array(); + preg_match_all('/\{(.+?)\}/', $pattern, $placeholders); + foreach ($placeholders[1] as $idx => $placeholder_name) { + $expected_url = preg_replace('/\{' . $placeholder_name . '\}/', $sampleArgs[$idx], $expected_url); + $parameters[$placeholder_name] = $sampleArgs[$idx]; + } + + $url = $generator->generate($name, $parameters); + $this->assertEqual($expected_url, $url, "Correct path generated for route $name."); + } + } + } + + /** + * Confirms correct behavior for non existent routes. + */ + function testNonExistentRoute() { + $connection = Database::getConnection(); + $this->fixtures->createTables($connection, 'test_routes'); + + $context = new RequestContext($this->requests[0]); + $generator = new UrlGenerator($connection, $context, "test_routes"); + + $msg = "Caught exception on generating URL for non-existent route."; + try { + $generator->generate('surelyNonExistentName'); + $this->fail($msg); + } catch (RouteNotFoundException $e) { + $this->pass($msg); + } + } +}