Issue #2098197 by dawehner, vijaycs85, damiankloip, tstoeckler: Add getAllRoutes() method to RouteProvider .
parent
9145204f16
commit
6819e5e0d6
|
@ -0,0 +1,147 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Contains \Drupal\Core\Routing\LazyLoadingRouteCollection.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Drupal\Core\Routing;
|
||||||
|
|
||||||
|
use Drupal\Core\Database\Connection;
|
||||||
|
use Iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a route collection that lists all routes of drupal.
|
||||||
|
*
|
||||||
|
* Internally this does load multiple routes over time, so it never have all the
|
||||||
|
* routes stored in memory.
|
||||||
|
*/
|
||||||
|
class LazyLoadingRouteCollection implements Iterator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the current loaded routes.
|
||||||
|
*
|
||||||
|
* @var \Symfony\Component\Routing\Route[]
|
||||||
|
*/
|
||||||
|
protected $elements;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains the amount of route which are loaded on each sql query.
|
||||||
|
*/
|
||||||
|
const ROUTE_LOADED_PER_TIME = 50;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains the current item the iterator points to.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $currentRoute = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The database connection.
|
||||||
|
*
|
||||||
|
* @var \Drupal\Core\Database\Connection
|
||||||
|
*/
|
||||||
|
protected $database;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the SQL table from which to read the routes.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $tableName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of routes in the router table.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $count;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a LazyLoadingRouteCollection instance.
|
||||||
|
*
|
||||||
|
* @param \Drupal\Core\Database\Connection $database
|
||||||
|
* The database connection.
|
||||||
|
* @param string $table
|
||||||
|
* (optional) The table to retrieve the route information.
|
||||||
|
*/
|
||||||
|
public function __construct(Connection $database, $table = 'router') {
|
||||||
|
$this->database = $database;
|
||||||
|
$this->tableName = $table;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the next routes into the elements array.
|
||||||
|
*
|
||||||
|
* @param int $offset
|
||||||
|
* The offset used in the db query.
|
||||||
|
*/
|
||||||
|
protected function loadNextElements($offset) {
|
||||||
|
$this->elements = array();
|
||||||
|
|
||||||
|
$query = $this->database->select($this->tableName);
|
||||||
|
$query->addField($this->tableName, 'name');
|
||||||
|
$query->addField($this->tableName, 'route');
|
||||||
|
$query->orderBy('name', 'ASC');
|
||||||
|
$query->range($offset, static::ROUTE_LOADED_PER_TIME);
|
||||||
|
$result = $query->execute()->fetchAllKeyed();
|
||||||
|
|
||||||
|
$routes = array();
|
||||||
|
foreach ($result as $name => $route) {
|
||||||
|
$routes[$name] = unserialize($route);
|
||||||
|
}
|
||||||
|
$this->elements = $routes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {inheritdoc}
|
||||||
|
*/
|
||||||
|
public function count() {
|
||||||
|
if (!isset($this->count)) {
|
||||||
|
$this->count = (int) $this->database->select($this->tableName)->countQuery()->execute();
|
||||||
|
}
|
||||||
|
return $this->count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function current() {
|
||||||
|
return current($this->elements);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function next() {
|
||||||
|
$result = next($this->elements);
|
||||||
|
if ($result === FALSE) {
|
||||||
|
$this->loadNextElements($this->currentRoute + 1);
|
||||||
|
}
|
||||||
|
$this->currentRoute++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function key() {
|
||||||
|
return key($this->elements);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function valid() {
|
||||||
|
return key($this->elements);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function rewind() {
|
||||||
|
$this->currentRoute = 0;
|
||||||
|
$this->loadNextElements($this->currentRoute);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -262,4 +262,11 @@ class RouteProvider implements RouteProviderInterface {
|
||||||
return $collection;
|
return $collection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getAllRoutes() {
|
||||||
|
return new LazyLoadingRouteCollection($this->connection, $this->tableName);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,4 +28,16 @@ interface RouteProviderInterface extends RouteProviderBaseInterface {
|
||||||
*/
|
*/
|
||||||
public function getRoutesByPattern($pattern);
|
public function getRoutesByPattern($pattern);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all the routes on the system.
|
||||||
|
*
|
||||||
|
* Usage of this method is discouraged for performance reasons. If possible,
|
||||||
|
* use RouteProviderInterface::getRoutesByNames() or
|
||||||
|
* RouteProviderInterface::getRoutesByPattern() instead.
|
||||||
|
*
|
||||||
|
* @return \Symfony\Component\Routing\Route[]
|
||||||
|
* An iterator of routes keyed by route name.
|
||||||
|
*/
|
||||||
|
public function getAllRoutes();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,5 +75,11 @@ class MockRouteProvider implements RouteProviderInterface {
|
||||||
return new RouteCollection();
|
return new RouteCollection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getAllRoutes() {
|
||||||
|
return $this->routes->all();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,113 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Contains \Drupal\Tests\Core\Routing\LazyLoadingRouteCollectionTest.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Drupal\Tests\Core\Routing;
|
||||||
|
|
||||||
|
use Drupal\Core\Routing\LazyLoadingRouteCollection;
|
||||||
|
use Drupal\Tests\UnitTestCase;
|
||||||
|
use Symfony\Component\Routing\Route;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the lazy loaded route collection.
|
||||||
|
*
|
||||||
|
* @group \Drupal
|
||||||
|
*
|
||||||
|
* @see \Drupal\Core\Routing\LazyLoadingRouteCollection
|
||||||
|
*/
|
||||||
|
class LazyLoadingRouteCollectionTest extends UnitTestCase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores all the routes used in the test.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $routes = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The tested route collection.
|
||||||
|
*
|
||||||
|
* @var \Drupal\Core\Routing\LazyLoadingRouteCollection
|
||||||
|
*/
|
||||||
|
protected $routeCollection;
|
||||||
|
|
||||||
|
public static function getInfo() {
|
||||||
|
return array(
|
||||||
|
'name' => 'Lazy loaded route collection',
|
||||||
|
'description' => 'Tests the lazy loaded route collection.',
|
||||||
|
'group' => 'Routing',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function setUp() {
|
||||||
|
for ($i = 0; $i < 20; $i++) {
|
||||||
|
$this->routes['test_route_' . $i] = new Route('/test-route-' . $i);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->routeCollection = new TestRouteCollection($this->routes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests iterating the lazy loading route collection.
|
||||||
|
*
|
||||||
|
* @see \Drupal\Core\Routing\LazyLoadingRouteCollection::current()
|
||||||
|
* @see \Drupal\Core\Routing\LazyLoadingRouteCollection::key()
|
||||||
|
* @see \Drupal\Core\Routing\LazyLoadingRouteCollection::rewind()
|
||||||
|
*/
|
||||||
|
public function testIterating() {
|
||||||
|
// Execute the foreach loop twice to ensure that rewind is called.
|
||||||
|
for ($i = 0; $i < 2; $i++) {
|
||||||
|
$route_names = array_keys($this->routes);
|
||||||
|
$count = 0;
|
||||||
|
foreach ($this->routeCollection as $route_name => $route) {
|
||||||
|
$this->assertEquals($route_names[$count], $route_name);
|
||||||
|
$this->assertEquals($this->routes[$route_names[$count]], $route);
|
||||||
|
|
||||||
|
$count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper class to "inject" loaded routes.
|
||||||
|
*/
|
||||||
|
class TestRouteCollection extends LazyLoadingRouteCollection {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
const ROUTE_LOADED_PER_TIME = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores all elements.
|
||||||
|
*
|
||||||
|
* @var \Symfony\Component\Routing\Route[]
|
||||||
|
*/
|
||||||
|
protected $allRoutes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a TestCollection instance.
|
||||||
|
*
|
||||||
|
* @param \Symfony\Component\Routing\Route[] $all_routes
|
||||||
|
* Contains all the routes used in the test.
|
||||||
|
*/
|
||||||
|
public function __construct(array $all_routes) {
|
||||||
|
$this->allRoutes = $all_routes;
|
||||||
|
$this->loadNextElements($this->currentRoute);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
protected function loadNextElements($offset) {
|
||||||
|
$elements = array_slice($this->allRoutes, $offset, static::ROUTE_LOADED_PER_TIME);
|
||||||
|
|
||||||
|
$this->elements = $elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue