Skip to content
This repository has been archived by the owner on Jul 4, 2018. It is now read-only.

Commit

Permalink
feature #1175 Added factory for RouteCollection, makes subclassing of…
Browse files Browse the repository at this point in the history
… RouteCollection possible. (lschricke)

This PR was merged into the 2.0.x-dev branch.

Discussion
----------

Added factory for RouteCollection, makes subclassing of RouteCollection possible.

Note: replaces #1174, which was targeting a wrong branch (and where I messed a bit with the commits ;)).

--

The aim of this PR is to allow developpers to subclass `Symfony\Component\Routing\RouteCollection` to change some of its behavior.

In most of my Silex apps, I figured I don't want the Symfony's `RouteCollection` regular behavior where if you define two routes with the same name (bad copy-paste for instance), the first route added simply gets overriden by the second. Instead, I would like to be able to throw an Exception if that happens. So I've written [a tiny subclass of RouteCollection](https://github.com/lschricke/symfony-strict-route-collection), but to be able to use it (through [a service provider like this](https://github.com/lschricke/silex-strict-route-collection-service-provider) for instance (needs to be updated for Silex 2)), I need to be able to replace `RouteCollection` by my subclass. This PR makes it possible.

Thanks! :)

Commits
-------

18f253f Added factory for RouteCollection, makes subclassing of RouteCollection possible.
  • Loading branch information
fabpot committed Jun 24, 2015
2 parents 5b7f26c + 18f253f commit 21632f0
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 4 deletions.
7 changes: 5 additions & 2 deletions src/Silex/Application.php
Expand Up @@ -64,16 +64,19 @@ public function __construct(array $values = array())

$app = $this;

$this['routes'] = function () {
$this['routes_factory'] = $this->factory(function () {
return new RouteCollection();
});
$this['routes'] = function () use ($app) {
return $app['routes_factory'];
};

$this['controllers'] = function () use ($app) {
return $app['controllers_factory'];
};

$this['controllers_factory'] = $this->factory(function () use ($app) {
return new ControllerCollection($app['route_factory']);
return new ControllerCollection($app['route_factory'], $app['routes_factory']);
});

$this['route_class'] = 'Silex\\Route';
Expand Down
10 changes: 8 additions & 2 deletions src/Silex/ControllerCollection.php
Expand Up @@ -42,10 +42,12 @@ class ControllerCollection
protected $defaultRoute;
protected $defaultController;
protected $prefix;
protected $routesFactory;

public function __construct(Route $defaultRoute)
public function __construct(Route $defaultRoute, $routesFactory = null)
{
$this->defaultRoute = $defaultRoute;
$this->routesFactory = $routesFactory;
$this->defaultController = function (Request $request) {
throw new \LogicException(sprintf('The "%s" route must have code to run when it matches.', $request->attributes->get('_route')));
};
Expand Down Expand Up @@ -186,7 +188,11 @@ public function __call($method, $arguments)
*/
public function flush($prefix = '')
{
$routes = new RouteCollection();
if (null === $this->routesFactory) {
$routes = new RouteCollection();
} else {
$routes = $this->routesFactory;
}

foreach ($this->controllers as $controller) {
if ($controller instanceof Controller) {
Expand Down
20 changes: 20 additions & 0 deletions tests/Silex/Tests/ApplicationTest.php
Expand Up @@ -23,6 +23,7 @@
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\Routing\RouteCollection;

/**
* Application test cases.
Expand Down Expand Up @@ -635,6 +636,21 @@ public function testViewListenersResponsesAreNotUsedIfNull()

$this->assertEquals('Hello view listener', $response->getContent());
}

public function testDefaultRoutesFactory()
{
$app = new Application();
$this->assertInstanceOf('Symfony\Component\Routing\RouteCollection', $app['routes']);
}

public function testOverriddenRoutesFactory()
{
$app = new Application();
$app['routes_factory'] = $app->factory(function () {
return new RouteCollectionSubClass();
});
$this->assertInstanceOf('Silex\Tests\RouteCollectionSubClass', $app['routes']);
}
}

class FooController
Expand All @@ -652,3 +668,7 @@ public function connect(Application $app)
return;
}
}

class RouteCollectionSubClass extends RouteCollection
{
}
25 changes: 25 additions & 0 deletions tests/Silex/Tests/ControllerCollectionTest.php
Expand Up @@ -11,10 +11,12 @@

namespace Silex\Tests;

use Silex\Application;
use Silex\Controller;
use Silex\ControllerCollection;
use Silex\Exception\ControllerFrozenException;
use Silex\Route;
use Symfony\Component\Routing\RouteCollection;

/**
* ControllerCollection test cases.
Expand Down Expand Up @@ -194,6 +196,25 @@ public function testNestedCollectionRouteCallbacks()
$this->assertEquals(array('before'), $c2->getRoute()->getOption('_before_middlewares'));
$this->assertEquals(array('before'), $c3->getRoute()->getOption('_before_middlewares'));
}

public function testRoutesFactoryOmitted()
{
$controllers = new ControllerCollection(new Route());
$routes = $controllers->flush();
$this->assertInstanceOf('Symfony\Component\Routing\RouteCollection', $routes);
}

public function testRoutesFactoryInConstructor()
{
$app = new Application();
$app['routes_factory'] = $app->factory(function () {
return new RouteCollectionSubClass2();
});

$controllers = new ControllerCollection(new Route(), $app['routes_factory']);
$routes = $controllers->flush();
$this->assertInstanceOf('Silex\Tests\RouteCollectionSubClass2', $routes);
}
}

class MyRoute1 extends Route
Expand All @@ -205,3 +226,7 @@ public function foo($value)
$this->foo = $value;
}
}

class RouteCollectionSubClass2 extends RouteCollection
{
}

0 comments on commit 21632f0

Please sign in to comment.