Introduce a default controller for pages with a _content request attribute.

8.0.x
Larry Garfield 2012-09-02 11:40:09 -05:00 committed by effulgentsia
parent 0bd8eed2cc
commit b9d5689987
6 changed files with 160 additions and 1 deletions

View File

@ -82,6 +82,7 @@ class CoreBundle extends Bundle
$dispatcher->addSubscriber(new \Drupal\Core\EventSubscriber\FinishResponseSubscriber());
$dispatcher->addSubscriber(new \Drupal\Core\EventSubscriber\RequestCloseSubscriber());
$dispatcher->addSubscriber(new \Drupal\Core\EventSubscriber\ConfigGlobalOverrideSubscriber());
$dispatcher->addSubscriber(new \Drupal\Core\EventSubscriber\RouteProcessorSubscriber());
$container->set('content_negotiation', $content_negotation);
$dispatcher->addSubscriber(\Drupal\Core\ExceptionController::getExceptionListener($container));

View File

@ -0,0 +1,72 @@
<?php
/**
* @file
* Definition of Drupal\Core\EventSubscriber\RouterListener.
*/
namespace Drupal\Core\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
/**
* Drupal-specific Router listener.
*
* This is the bridge from the kernel to the UrlMatcher.
*/
class RouteProcessorSubscriber implements EventSubscriberInterface {
/**
* The Matcher object for this listener.
*
* This property is private in the base class, so we have to hack around it.
*
* @var Symfony\Component\Router\Matcher\UrlMatcherInterface
*/
protected $urlMatcher;
/**
* The Logging object for this listener.
*
* This property is private in the base class, so we have to hack around it.
*
* @var Symfony\Component\HttpKernel\Log\LoggerInterface
*/
protected $logger;
public function __construct() {
}
/**
* Sets a default controller for a route if one was not specified.
*/
public function onRequestSetController(GetResponseEvent $event) {
$request = $event->getRequest();
if (!$request->attributes->has('_controller') && $request->attributes->has('_content')) {
$request->attributes->set('_controller', '\Drupal\Core\HtmlPageController::content');
}
}
/**
* Registers the methods in this class that should be listeners.
*
* @return array
* An array of event listener definitions.
*/
static function getSubscribedEvents() {
// The RouterListener has priority 32, and we need to run after that.
$events[KernelEvents::REQUEST][] = array('onRequestSetController', 30);
return $events;
}
}

View File

@ -0,0 +1,57 @@
<?php
namespace Drupal\Core;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class HtmlPageController {
public function content(Request $request, $_content) {
$content_controller = $this->getContentController($_content);
$page_callback_result = call_user_func_array($content_controller, array());
return new Response(drupal_render_page($page_callback_result));
}
protected function getContentController($controller) {
if (is_array($controller) || (is_object($controller) && method_exists($controller, '__invoke'))) {
return $controller;
}
if (FALSE === strpos($controller, ':')) {
if (method_exists($controller, '__invoke')) {
return new $controller;
} elseif (function_exists($controller)) {
return $controller;
}
}
list($controller, $method) = $this->createController($controller);
if (!method_exists($controller, $method)) {
throw new \InvalidArgumentException(sprintf('Method "%s::%s" does not exist.', get_class($controller), $method));
}
return array($controller, $method);
}
protected function createController($controller) {
if (false === strpos($controller, '::')) {
throw new \InvalidArgumentException(sprintf('Unable to find controller "%s".', $controller));
}
list($class, $method) = explode('::', $controller, 2);
if (!class_exists($class)) {
throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class));
}
return array(new $class(), $method);
}
}

View File

@ -25,9 +25,21 @@ class RouterTest extends WebTestBase {
);
}
/**
* Confirms that the router can get to a controller.
*/
public function testCanRoute() {
$this->drupalGet('router_test/test1');
$this->assertRaw('test1', 'The correct string was returned because the route was successful.');
}
/**
* Confirms that our default controller logic works properly.
*/
public function testDefaultController() {
$this->drupalGet('router_test/test2');
$this->assertRaw('test2', 'The correct string was returned because the route was successful.');
$this->assertRaw('</html>', 'Page markup was found.');
}
}

View File

@ -1,11 +1,16 @@
<?php
/**
* @file
* Definition of Drupal\router_test\TestControllers.
*/
namespace Drupal\router_test;
use Symfony\Component\HttpFoundation\Response;
/**
* Description of TestControllers
* Controller routines for testing the routing system.
*/
class TestControllers {
@ -13,5 +18,9 @@ class TestControllers {
return new Response('test1');
}
public function test2() {
return "test2";
}
}

View File

@ -3,6 +3,9 @@
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
/**
* Implements hook_router_info().
*/
function router_test_route_info() {
$collection = new RouteCollection();
@ -11,5 +14,10 @@ function router_test_route_info() {
));
$collection->add('router_test_1', $route);
$route = new Route('router_test/test2', array(
'_content' => '\Drupal\router_test\TestControllers::test2'
));
$collection->add('router_test_2', $route);
return $collection;
}