Commit e3ddad54 authored by Fabien Potencier's avatar Fabien Potencier

added the possibility for settings set on a controller collection to influence...

added the possibility for settings set on a controller collection to influence controllers register later on
parent 0356873a
...@@ -3,7 +3,7 @@ Changelog ...@@ -3,7 +3,7 @@ Changelog
This changelog references all backward incompatibilities as we introduce them: This changelog references all backward incompatibilities as we introduce them:
* **2012-05-20**: Added a way to define settings for all routes of a collection. * **2012-05-20**: Added a way to define settings on a controller collection.
* **2012-05-20**: The Request instance is not available anymore from the * **2012-05-20**: The Request instance is not available anymore from the
Application after it has been handled. Application after it has been handled.
......
...@@ -436,9 +436,9 @@ If a route middleware does not return a Symfony HTTP Response or ``null``, a ...@@ -436,9 +436,9 @@ If a route middleware does not return a Symfony HTTP Response or ``null``, a
Global Configuration Global Configuration
-------------------- --------------------
If a route setting must be applied to all routes (a converter, a middleware, a If a controller setting must be applied to all controllers (a converter, a
requirement, or a default value), you can configure it on middleware, a requirement, or a default value), you can configure it on
``$app['controllers']``, which holds all controllers:: ``$app['controllers']``, which holds all application controllers::
$app['controllers'] $app['controllers']
->value('id', '1') ->value('id', '1')
...@@ -449,8 +449,8 @@ requirement, or a default value), you can configure it on ...@@ -449,8 +449,8 @@ requirement, or a default value), you can configure it on
->middleware(function () { // ... }) ->middleware(function () { // ... })
; ;
These settings can be set before or after controller definitions and settings These settings are applied to already registered controllers and they become
defined on a controller always override the globally configured one. the defaults for new controllers.
Error handlers Error handlers
-------------- --------------
...@@ -596,12 +596,13 @@ blog home page, and ``/forum/`` to the forum home page. ...@@ -596,12 +596,13 @@ blog home page, and ``/forum/`` to the forum home page.
Application, you are in fact calling them on a default instance of Application, you are in fact calling them on a default instance of
``ControllerCollection`` (stored in ``$app['controllers']``). ``ControllerCollection`` (stored in ``$app['controllers']``).
Another benefit is the ability to apply default settings on a set of Another benefit is the ability to apply settings on a set of controllers very
controllers very easily. Building on the example from the middleware section, easily. Building on the example from the middleware section, here is how you
here is how you would secure all controllers for all backend routes:: would secure all controllers for the backend collection::
$backend = new ControllerCollection(); $backend = new ControllerCollection();
// ensure that all controllers require logged-in users
$backend->middleware($mustBeLogged); $backend->middleware($mustBeLogged);
.. tip:: .. tip::
......
...@@ -21,11 +21,11 @@ use Symfony\Component\Routing\Route; ...@@ -21,11 +21,11 @@ use Symfony\Component\Routing\Route;
*/ */
class Controller class Controller
{ {
protected $route;
private $routeName; private $routeName;
private $isFrozen = false; private $isFrozen = false;
protected $route;
/** /**
* Constructor. * Constructor.
* *
......
...@@ -51,9 +51,11 @@ class ControllerCollection extends Controller ...@@ -51,9 +51,11 @@ class ControllerCollection extends Controller
*/ */
public function match($pattern, $to) public function match($pattern, $to)
{ {
$route = new Route($pattern, array('_controller' => $to)); $route = clone $this->route;
$controller = new Controller($route); $route->setPattern($pattern);
$this->add($controller); $route->setDefault('_controller', $to);
$this->controllers[] = $controller = new Controller($route);
return $controller; return $controller;
} }
...@@ -111,13 +113,101 @@ class ControllerCollection extends Controller ...@@ -111,13 +113,101 @@ class ControllerCollection extends Controller
} }
/** /**
* Adds a controller to the staging area. * {@inheritDoc}
*
* @param Controller $controller
*/ */
public function add(Controller $controller) public function assert($variable, $regexp)
{ {
$this->controllers[] = $controller; parent::assert($variable, $regexp);
foreach ($this->controllers as $controller) {
$controller->assert($variable, $regexp);
}
return $this;
}
/**
* {@inheritDoc}
*/
public function value($variable, $default)
{
parent::value($variable, $default);
foreach ($this->controllers as $controller) {
$controller->value($variable, $default);
}
return $this;
}
/**
* {@inheritDoc}
*/
public function convert($variable, $callback)
{
parent::convert($variable, $callback);
foreach ($this->controllers as $controller) {
$controller->convert($variable, $callback);
}
return $this;
}
/**
* {@inheritDoc}
*/
public function method($method)
{
parent::method($method);
foreach ($this->controllers as $controller) {
$controller->method($method);
}
return $this;
}
/**
* {@inheritDoc}
*/
public function requireHttp()
{
parent::requireHttp();
foreach ($this->controllers as $controller) {
$controller->requireHttp();
}
return $this;
}
/**
* {@inheritDoc}
*/
public function requireHttps()
{
parent::requireHttps();
foreach ($this->controllers as $controller) {
$controller->requireHttps();
}
return $this;
}
/**
* {@inheritDoc}
*/
public function middleware($callback)
{
parent::middleware($callback);
foreach ($this->controllers as $controller) {
$controller->middleware($callback);
}
return $this;
} }
/** /**
...@@ -130,8 +220,6 @@ class ControllerCollection extends Controller ...@@ -130,8 +220,6 @@ class ControllerCollection extends Controller
$routes = new RouteCollection(); $routes = new RouteCollection();
foreach ($this->controllers as $controller) { foreach ($this->controllers as $controller) {
$route = $controller->getRoute();
if (!$name = $controller->getRouteName()) { if (!$name = $controller->getRouteName()) {
$name = $controller->generateRouteName($prefix); $name = $controller->generateRouteName($prefix);
while ($routes->get($name)) { while ($routes->get($name)) {
...@@ -139,11 +227,7 @@ class ControllerCollection extends Controller ...@@ -139,11 +227,7 @@ class ControllerCollection extends Controller
} }
$controller->bind($name); $controller->bind($name);
} }
$routes->add($name, $controller->getRoute());
$this->mergeGlobalSettings($route);
$routes->add($name, $route);
$controller->freeze(); $controller->freeze();
} }
...@@ -151,22 +235,4 @@ class ControllerCollection extends Controller ...@@ -151,22 +235,4 @@ class ControllerCollection extends Controller
return $routes; return $routes;
} }
protected function mergeGlobalSettings(Route $route)
{
$route->setOption('_middlewares', array_merge((array) $this->route->getOption('_middlewares'), (array) $route->getOption('_middlewares')));
$route->setOption('_converters', array_replace((array) $this->route->getOption('_converters'), (array) $route->getOption('_converters')));
foreach ($this->route->getDefaults() as $name => $value) {
if (!$route->hasDefault($name)) {
$route->setDefault($name, $value);
}
}
foreach ($this->route->getRequirements() as $name => $value) {
if (!$route->getRequirement($name)) {
$route->setRequirement($name, $value);
}
}
}
} }
...@@ -34,8 +34,8 @@ class ControllerCollectionTest extends \PHPUnit_Framework_TestCase ...@@ -34,8 +34,8 @@ class ControllerCollectionTest extends \PHPUnit_Framework_TestCase
public function testGetRouteCollectionWithRoutes() public function testGetRouteCollectionWithRoutes()
{ {
$controllers = new ControllerCollection(); $controllers = new ControllerCollection();
$controllers->add(new Controller(new Route('/foo'))); $controllers->match('/foo', function () {});
$controllers->add(new Controller(new Route('/bar'))); $controllers->match('/bar', function () {});
$routes = $controllers->flush(); $routes = $controllers->flush();
$this->assertEquals(2, count($routes->all())); $this->assertEquals(2, count($routes->all()));
...@@ -45,13 +45,8 @@ class ControllerCollectionTest extends \PHPUnit_Framework_TestCase ...@@ -45,13 +45,8 @@ class ControllerCollectionTest extends \PHPUnit_Framework_TestCase
{ {
$controllers = new ControllerCollection(); $controllers = new ControllerCollection();
$fooController = new Controller(new Route('/foo')); $fooController = $controllers->match('/foo', function () {})->bind('foo');
$fooController->bind('foo'); $barController = $controllers->match('/bar', function () {})->bind('bar');
$controllers->add($fooController);
$barController = new Controller(new Route('/bar'));
$barController->bind('bar');
$controllers->add($barController);
$controllers->flush(); $controllers->flush();
...@@ -72,8 +67,7 @@ class ControllerCollectionTest extends \PHPUnit_Framework_TestCase ...@@ -72,8 +67,7 @@ class ControllerCollectionTest extends \PHPUnit_Framework_TestCase
{ {
$controllers = new ControllerCollection(); $controllers = new ControllerCollection();
$mountedRootController = new Controller(new Route('/')); $mountedRootController = $controllers->match('/', function () {});
$controllers->add($mountedRootController);
$mainRootController = new Controller(new Route('/')); $mainRootController = new Controller(new Route('/'));
$r = new \ReflectionObject($mainRootController); $r = new \ReflectionObject($mainRootController);
...@@ -90,74 +84,69 @@ class ControllerCollectionTest extends \PHPUnit_Framework_TestCase ...@@ -90,74 +84,69 @@ class ControllerCollectionTest extends \PHPUnit_Framework_TestCase
{ {
$controllers = new ControllerCollection(); $controllers = new ControllerCollection();
$controllers->add(new Controller(new Route('/a-a'))); $controllers->match('/a-a', function () {});
$controllers->add(new Controller(new Route('/a_a'))); $controllers->match('/a_a', function () {});
$routes = $controllers->flush(); $routes = $controllers->flush();
$this->assertCount(2, $routes->all()); $this->assertCount(2, $routes->all());
$this->assertEquals(array('_a_a', '_a_a_'), array_keys($routes->all())); $this->assertEquals(array('_a_a', '_a_a_'), array_keys($routes->all()));
} }
public function testRouteSettingsFromCollection() public function testAssert()
{
$controllers = new ControllerCollection();
$controllers->assert('id', '\d+');
$controller = $controllers->match('/{id}/{name}/{extra}', function () {})->assert('name', '\w+')->assert('extra', '.*');
$controllers->assert('extra', '\w+');
$this->assertEquals('\d+', $controller->getRoute()->getRequirement('id'));
$this->assertEquals('\w+', $controller->getRoute()->getRequirement('name'));
$this->assertEquals('\w+', $controller->getRoute()->getRequirement('extra'));
}
public function testValue()
{ {
$controller = new Controller(new Route('/')); $controllers = new ControllerCollection();
$controller $controllers->value('id', '1');
->value('bar', 'bar') $controller = $controllers->match('/{id}/{name}/{extra}', function () {})->value('name', 'Fabien')->value('extra', 'Symfony');
->value('baz', 'baz') $controllers->value('extra', 'Twig');
->assert('bar', 'bar')
->assert('baz', 'baz') $this->assertEquals('1', $controller->getRoute()->getDefault('id'));
->convert('bar', $converterBar = function () {}) $this->assertEquals('Fabien', $controller->getRoute()->getDefault('name'));
->middleware($middleware1 = function () {}) $this->assertEquals('Twig', $controller->getRoute()->getDefault('extra'));
->bind('home') }
;
$controller1 = new Controller(new Route('/'));
$controller1
->requireHttp()
->method('post')
->convert('foo', $converterFoo1 = function () {})
->bind('home1')
;
public function testConvert()
{
$controllers = new ControllerCollection(); $controllers = new ControllerCollection();
$controllers->add($controller); $controllers->convert('id', '1');
$controllers->add($controller1); $controller = $controllers->match('/{id}/{name}/{extra}', function () {})->convert('name', 'Fabien')->convert('extra', 'Symfony');
$controllers->convert('extra', 'Twig');
$controllers
->value('foo', 'foo')
->value('baz', 'not_used')
->assert('foo', 'foo')
->assert('baz', 'not_used')
->requireHttps()
->method('get')
->convert('foo', $converterFoo = function () {})
->middleware($middleware2 = function () {})
;
$routes = $controllers->flush(); $this->assertEquals(array('id' => '1', 'name' => 'Fabien', 'extra' => 'Twig'), $controller->getRoute()->getOption('_converters'));
}
public function testRequireHttp()
{
$controllers = new ControllerCollection();
$controllers->requireHttp();
$controller = $controllers->match('/{id}/{name}/{extra}', function () {})->requireHttps();
$this->assertEquals('https', $controller->getRoute()->getRequirement('_scheme'));
$controllers->requireHttp();
$this->assertEquals('http', $controller->getRoute()->getRequirement('_scheme'));
}
public function testMiddleware()
{
$controllers = new ControllerCollection();
$controllers->middleware('mid1');
$controller = $controllers->match('/{id}/{name}/{extra}', function () {})->middleware('mid2');
$controllers->middleware('mid3');
$this->assertEquals(array( $this->assertEquals(array('mid1', 'mid2', 'mid3'), $controller->getRoute()->getOption('_middlewares'));
'foo' => 'foo',
'bar' => 'bar',
'baz' => 'baz',
), $routes->get('home')->getDefaults());
$this->assertEquals(array(
'foo' => 'foo',
'bar' => 'bar',
'baz' => 'baz',
'_scheme' => 'https',
'_method' => 'get',
), $routes->get('home')->getRequirements());
$this->assertEquals(array(
'foo' => $converterFoo,
'bar' => $converterBar,
), $routes->get('home')->getOption('_converters'));
$this->assertEquals(array($middleware1, $middleware2), $routes->get('home')->getOption('_middlewares'));
$this->assertEquals('http', $routes->get('home1')->getRequirement('_scheme'));
$this->assertEquals('post', $routes->get('home1')->getRequirement('_method'));
$this->assertEquals(array('foo' => $converterFoo1), $routes->get('home1')->getOption('_converters'));
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment