Introduce a default controller for pages with a _content request attribute.
parent
0bd8eed2cc
commit
b9d5689987
|
@ -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));
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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.');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue