Issue #2026431 by YesCT, dawehner, Crell: Make ContentNegotiation a 'internal' service, used only by the router, so that core or contrib can implement real negotiation.

8.0.x
catch 2014-03-24 15:39:43 +00:00
parent 3e2681096f
commit 99b9a6a579
5 changed files with 131 additions and 89 deletions

View File

@ -429,27 +429,21 @@ services:
tags:
- { name: route_enhancer, priority: 1000 }
arguments: ['@authentication']
route_enhancer.content_controller:
class: Drupal\Core\Routing\Enhancer\ContentControllerEnhancer
arguments: ['@content_negotiation']
tags:
- { name: route_enhancer, priority: 30 }
route_enhancer.ajax:
class: Drupal\Core\Routing\Enhancer\AjaxEnhancer
arguments: ['@content_negotiation']
tags:
- { name: route_enhancer, priority: 15 }
- { name: legacy_route_enhancer, priority: 15 }
route_enhancer.entity:
class: Drupal\Core\Entity\Enhancer\EntityRouteEnhancer
arguments: ['@controller_resolver', '@entity.manager', '@form_builder']
tags:
- { name: route_enhancer, priority: 20 }
route_enhancer.form:
class: Drupal\Core\Routing\Enhancer\FormEnhancer
route_content_controller_subscriber:
class: Drupal\Core\EventSubscriber\ContentControllerSubscriber
arguments: ['@content_negotiation']
tags:
- { name: event_subscriber }
route_content_form_controller_subscriber:
class: Drupal\Core\EventSubscriber\ContentFormControllerSubscriber
arguments: ['@service_container', '@controller_resolver', '@form_builder']
tags:
- { name: route_enhancer, priority: 10 }
- { name: event_subscriber }
route_special_attributes_subscriber:
class: Drupal\Core\EventSubscriber\SpecialAttributesRouteSubscriber
tags:

View File

@ -0,0 +1,93 @@
<?php
/**
* @file
* Contains \Drupal\Core\EventSubscriber\ContentControllerSubscriber.
*/
namespace Drupal\Core\EventSubscriber;
use Drupal\Core\ContentNegotiation;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
/**
* Defines a subscriber for setting the format of the request.
*/
class ContentControllerSubscriber implements EventSubscriberInterface {
/**
* Content negotiation library.
*
* @var \Drupal\Core\ContentNegotiation
*/
protected $negotiation;
/**
* Constructs a new ContentControllerSubscriber object.
*
* @param \Drupal\Core\ContentNegotiation $negotiation
* The Content Negotiation service.
*/
public function __construct(ContentNegotiation $negotiation) {
$this->negotiation = $negotiation;
}
/**
* Associative array of supported mime types and their appropriate controller.
*
* @var array
*/
protected $types = array(
'drupal_dialog' => 'controller.dialog:dialog',
'drupal_modal' => 'controller.dialog:modal',
'html' => 'controller.page:content',
'drupal_ajax' => 'controller.ajax:content',
);
/**
* Sets the derived request format on the request.
*
* @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
* The event to process.
*/
public function onRequestDeriveFormat(GetResponseEvent $event) {
$request = $event->getRequest();
if (!$request->attributes->get('_format')) {
$request->setRequestFormat($this->negotiation->getContentType($request));
}
}
/**
* Sets the _controller on a request based on the request format.
*
* @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
* The event to process.
*/
public function onRequestDeriveContentWrapper(GetResponseEvent $event) {
$request = $event->getRequest();
$controller = $request->attributes->get('_controller');
if (empty($controller) && ($type = $request->getRequestFormat())) {
if (isset($this->types[$type])) {
$request->attributes->set('_controller', $this->types[$type]);
}
}
}
/**
* Registers the methods in this class that should be listeners.
*
* @return array
* An array of event listener definitions.
*/
static function getSubscribedEvents() {
$events[KernelEvents::REQUEST][] = array('onRequestDeriveFormat', 31);
$events[KernelEvents::REQUEST][] = array('onRequestDeriveContentWrapper', 30);
return $events;
}
}

View File

@ -2,22 +2,23 @@
/**
* @file
* Contains \Drupal\Core\Routing\Enhancer\FormEnhancer.
* Definition of Drupal\Core\EventSubscriber\ContentFormControllerSubscriber.
*/
namespace Drupal\Core\Routing\Enhancer;
namespace Drupal\Core\EventSubscriber;
use Drupal\Core\Controller\HtmlFormController;
use Drupal\Core\Controller\ControllerResolverInterface;
use Drupal\Core\Form\FormBuilderInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerInterface;
/**
* Enhances a form route with the appropriate controller.
* Subscriber for setting wrapping form logic.
*/
class FormEnhancer implements RouteEnhancerInterface {
class ContentFormControllerSubscriber implements EventSubscriberInterface {
/**
* The service container.
@ -41,7 +42,7 @@ class FormEnhancer implements RouteEnhancerInterface {
protected $formBuilder;
/**
* Constructs a new \Drupal\Core\Routing\Enhancer\FormEnhancer object.
* Constructs a new ContentFormControllerSubscriber object.
*
* @param \Symfony\Component\DependencyInjection\ContainerInterface $container
* The service container.
@ -57,14 +58,29 @@ class FormEnhancer implements RouteEnhancerInterface {
}
/**
* {@inheritdoc}
* Sets the _controllere on a request based on the request format.
*
* @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
* The event to process.
*/
public function enhance(array $defaults, Request $request) {
if (!empty($defaults['_form'])) {
$wrapper = new HtmlFormController($this->resolver, $this->container, $defaults['_form'], $this->formBuilder);
$defaults['_content'] = array($wrapper, 'getContentResult');
public function onRequestDeriveFormWrapper(GetResponseEvent $event) {
$request = $event->getRequest();
if ($form = $request->attributes->get('_form')) {
$wrapper = new HtmlFormController($this->resolver, $this->container, $form, $this->formBuilder);
$request->attributes->set('_content', array($wrapper, 'getContentResult'));
}
return $defaults;
}
/**
* Registers the methods in this class that should be listeners.
*
* @return array
* An array of event listener definitions.
*/
static function getSubscribedEvents() {
$events[KernelEvents::REQUEST][] = array('onRequestDeriveFormWrapper', 29);
return $events;
}
}

View File

@ -1,61 +0,0 @@
<?php
/**
* @file
* Contains \Drupal\Core\Routing\Enhancer\ContentControllerEnhancer.
*/
namespace Drupal\Core\Routing\Enhancer;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerInterface;
use Drupal\Core\ContentNegotiation;
/**
* Enhances a route to select a controller based on the mime type of the request.
*/
class ContentControllerEnhancer implements RouteEnhancerInterface {
/**
* Content negotiation library.
*
* @var \Drupal\Core\ContentNegotiation
*/
protected $negotiation;
/**
* Associative array of supported mime types and their appropriate controller.
*
* @var array
*/
protected $types = array(
'drupal_dialog' => 'controller.dialog:dialog',
'drupal_modal' => 'controller.dialog:modal',
'html' => 'controller.page:content',
'drupal_ajax' => 'controller.ajax:content',
);
/**
* Constructs a new ContentControllerEnhancer object.
*
* @param \Drupal\Core\ContentNegotiation $negotiation
* The Content Negotiation service.
*/
public function __construct(ContentNegotiation $negotiation) {
$this->negotiation = $negotiation;
}
/**
* {@inheritdoc}
*/
public function enhance(array $defaults, Request $request) {
// If no controller is set and either _content is set or the request is
// for a dialog or modal, then enhance.
if (empty($defaults['_controller']) && ($type = $this->negotiation->getContentType($request))) {
if (isset($this->types[$type])) {
$defaults['_controller'] = $this->types[$type];
}
}
return $defaults;
}
}

View File

@ -1,7 +1,7 @@
system.ajax:
path: '/system/ajax'
defaults:
_controller: '\Drupal\system\Controller\FormAjaxController::content'
_content: '\Drupal\system\Controller\FormAjaxController::content'
options:
_theme: ajax_base_page
requirements: