Issue #2368275 by martin107, dawehner, znerol, Crell, Wim Leers: EntityRouteEnhancer and ContentFormControllerSubscriber implicitly depend on too many services

8.0.x
Nathaniel Catchpole 2014-11-28 15:04:11 +00:00
parent 58480ee670
commit 07a6a686a1
7 changed files with 74 additions and 94 deletions

View File

@ -639,7 +639,6 @@ services:
arguments: ['@authentication', '@current_user']
route_enhancer.entity:
class: Drupal\Core\Entity\Enhancer\EntityRouteEnhancer
arguments: ['@controller_resolver', '@entity.manager', '@form_builder']
tags:
- { name: route_enhancer, priority: 20 }
route_content_controller_subscriber:
@ -647,12 +646,6 @@ services:
arguments: ['@content_negotiation']
tags:
- { name: event_subscriber }
route_content_form_controller_subscriber:
class: Drupal\Core\EventSubscriber\ContentFormControllerSubscriber
arguments: ['@class_resolver', '@controller_resolver', '@form_builder']
parent: container.trait
tags:
- { name: event_subscriber }
route_special_attributes_subscriber:
class: Drupal\Core\EventSubscriber\SpecialAttributesRouteSubscriber
tags:
@ -688,7 +681,12 @@ services:
arguments: ['@title_resolver']
tags:
- { name: render.main_content_renderer, format: drupal_modal }
controller.form:
class: Drupal\Core\Controller\HtmlFormController
arguments: ['@controller_resolver', '@form_builder', '@class_resolver']
controller.entity_form:
class: Drupal\Core\Entity\HtmlEntityFormController
arguments: ['@controller_resolver', '@form_builder', '@entity.manager']
router_listener:
class: Symfony\Component\HttpKernel\EventListener\RouterListener
tags:

View File

@ -19,12 +19,6 @@ use Symfony\Component\HttpFoundation\Request;
*/
abstract class FormController {
use DependencySerializationTrait;
/**
* The form definition. The format may vary depending on the child class.
*
* @var string
*/
protected $formDefinition;
/**
* The controller resolver.
@ -63,14 +57,15 @@ abstract class FormController {
* The render array that results from invoking the controller.
*/
public function getContentResult(Request $request) {
$form_object = $this->getFormObject($request, $this->formDefinition);
$form_arg = $this->getFormArgument($request);
$form_object = $this->getFormObject($request, $form_arg);
// Add the form and form_state to trick the getArguments method of the
// controller resolver.
$form_state = new FormState();
$request->attributes->set('form', array());
$request->attributes->set('form', []);
$request->attributes->set('form_state', $form_state);
$args = $this->controllerResolver->getArguments($request, array($form_object, 'buildForm'));
$args = $this->controllerResolver->getArguments($request, [$form_object, 'buildForm']);
$request->attributes->remove('form');
$request->attributes->remove('form_state');
@ -81,6 +76,26 @@ abstract class FormController {
return $this->formBuilder->buildForm($form_object, $form_state);
}
/**
* Extracts the form argument string from a request.
*
* Depending on the type of form the argument string may be stored in a
* different request attribute.
*
* One example of a route definition is given below.
* @code
* defaults:
* _form: Drupal\example\Form\ExampleForm
* @endcode
*
* @param \Symfony\Component\HttpFoundation\Request $request
* The request object from which to extract a form definition string.
*
* @return string
* The form definition string.
*/
abstract protected function getFormArgument(Request $request);
/**
* Returns the object used to build the form.
*

View File

@ -9,29 +9,13 @@ namespace Drupal\Core\Controller;
use Drupal\Core\Form\FormBuilderInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\DependencyInjection\ClassResolverInterface;
use Drupal\Core\Controller\ControllerResolverInterface;
/**
* Wrapping controller for forms that serve as the main page body.
*/
class HtmlFormController extends FormController {
/**
* The injection container for this object.
*
* @var \Symfony\Component\DependencyInjection\ContainerInterface
*/
protected $container;
/**
* The name of a class implementing FormInterface that defines a form.
*
* @var string
*/
protected $formClass;
/**
* The class resolver.
*
@ -41,12 +25,24 @@ class HtmlFormController extends FormController {
/**
* Constructs a new \Drupal\Core\Routing\Enhancer\FormEnhancer object.
*
* @param \Drupal\Core\Controller\ControllerResolverInterface $controller_resolver
* The controller resolver.
* @param \Drupal\Core\Form\FormBuilderInterface $form_builder
* The form builder.
* @param \Drupal\Core\DependencyInjection\ClassResolverInterface $class_resolver
* The class resolver.
*/
public function __construct(ClassResolverInterface $class_resolver, ControllerResolverInterface $controller_resolver, ContainerInterface $container, $class, FormBuilderInterface $form_builder) {
public function __construct(ControllerResolverInterface $controller_resolver, FormBuilderInterface $form_builder, ClassResolverInterface $class_resolver) {
parent::__construct($controller_resolver, $form_builder);
$this->classResolver = $class_resolver;
$this->container = $container;
$this->formDefinition = $class;
}
/**
* @{inheritDoc}
*/
protected function getFormArgument(Request $request) {
return $request->attributes->get('_form');
}
/**

View File

@ -7,10 +7,6 @@
namespace Drupal\Core\Entity\Enhancer;
use Drupal\Core\Controller\ControllerResolverInterface;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Entity\HtmlEntityFormController;
use Drupal\Core\Form\FormBuilderInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerInterface;
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
@ -20,51 +16,13 @@ use Symfony\Cmf\Component\Routing\RouteObjectInterface;
*/
class EntityRouteEnhancer implements RouteEnhancerInterface {
/**
* The controller resolver.
*
* @var \Drupal\Core\Controller\ControllerResolverInterface
*/
protected $resolver;
/**
* The entity manager service.
*
* @var \Drupal\Core\Entity\EntityManagerInterface
*/
protected $manager;
/**
* The form builder.
*
* @var \Drupal\Core\Form\FormBuilderInterface
*/
protected $formBuilder;
/**
* Constructs a new EntityRouteEnhancer object.
*
* @param \Drupal\Core\Controller\ControllerResolverInterface $resolver
* The controller resolver.
* @param \Drupal\Core\Entity\EntityManagerInterface $manager
* The entity manager.
* @param \Drupal\Core\Form\FormBuilderInterface $form_builder
* The form builder.
*/
public function __construct(ControllerResolverInterface $resolver, EntityManagerInterface $manager, FormBuilderInterface $form_builder) {
$this->resolver = $resolver;
$this->manager = $manager;
$this->formBuilder = $form_builder;
}
/**
* {@inheritdoc}
*/
public function enhance(array $defaults, Request $request) {
if (empty($defaults['_controller'])) {
if (!empty($defaults['_entity_form'])) {
$wrapper = new HtmlEntityFormController($this->resolver, $this->manager, $this->formBuilder, $defaults['_entity_form']);
$defaults['_controller'] = array($wrapper, 'getContentResult');
$defaults['_controller'] = 'controller.entity_form:getContentResult';
}
elseif (!empty($defaults['_entity_list'])) {
$defaults['_controller'] = '\Drupal\Core\Entity\Controller\EntityListController::listing';

View File

@ -29,17 +29,21 @@ class HtmlEntityFormController extends FormController {
*
* @param \Drupal\Core\Controller\ControllerResolverInterface $resolver
* The controller resolver.
* @param \Drupal\Core\Entity\EntityManagerInterface $manager
* The entity manager.
* @param \Drupal\Core\Form\FormBuilderInterface $form_builder
* The form builder.
* @param string $form_definition
* The definition of this form, usually found in $defaults['_entity_form'].
* @param \Drupal\Core\Entity\EntityManagerInterface $manager
* The entity manager.
*/
public function __construct(ControllerResolverInterface $resolver, EntityManagerInterface $manager, FormBuilderInterface $form_builder, $form_definition) {
public function __construct(ControllerResolverInterface $resolver, FormBuilderInterface $form_builder, EntityManagerInterface $manager) {
parent::__construct($resolver, $form_builder);
$this->manager = $manager;
$this->formDefinition = $form_definition;
}
/**
* @{inheritDoc}
*/
protected function getFormArgument(Request $request) {
return $request->attributes->get('_entity_form');
}
/**
@ -71,7 +75,7 @@ class HtmlEntityFormController extends FormController {
$entity = $request->attributes->get($entity_type);
}
else {
$entity = $this->manager->getStorage($entity_type)->create(array());
$entity = $this->manager->getStorage($entity_type)->create([]);
}
return $this->manager->getFormObject($entity_type, $operation)->setEntity($entity);

View File

@ -53,6 +53,20 @@ class ContentControllerSubscriber implements EventSubscriberInterface {
}
}
/**
* Sets the _controller on a request when a _form is defined.
*
* @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
* The event to process.
*/
public function onRequestDeriveFormWrapper(GetResponseEvent $event) {
$request = $event->getRequest();
if ($request->attributes->has('_form')) {
$request->attributes->set('_controller', 'controller.form:getContentResult');
}
}
/**
* Registers the methods in this class that should be listeners.
*
@ -61,6 +75,7 @@ class ContentControllerSubscriber implements EventSubscriberInterface {
*/
static function getSubscribedEvents() {
$events[KernelEvents::REQUEST][] = array('onRequestDeriveFormat', 31);
$events[KernelEvents::REQUEST][] = array('onRequestDeriveFormWrapper', 29);
return $events;
}

View File

@ -24,11 +24,7 @@ class EntityRouteEnhancerTest extends UnitTestCase {
* @see \Drupal\Core\Entity\Enhancer\EntityRouteEnhancer::enhancer()
*/
public function testEnhancer() {
$controller_resolver = $this->getMock('Drupal\Core\Controller\ControllerResolverInterface');
$entity_manager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface');
$form_builder = $this->getMock('Drupal\Core\Form\FormBuilderInterface');
$route_enhancer = new EntityRouteEnhancer($controller_resolver, $entity_manager, $form_builder);
$route_enhancer = new EntityRouteEnhancer();
// Set a controller to ensure it is not overridden.
$request = new Request();
@ -43,9 +39,7 @@ class EntityRouteEnhancerTest extends UnitTestCase {
$defaults = array();
$defaults['_entity_form'] = 'entity_test.default';
$new_defaults = $route_enhancer->enhance($defaults, $request);
$this->assertTrue(is_callable($new_defaults['_controller']));
$this->assertInstanceOf('\Drupal\Core\Entity\HtmlEntityFormController', $new_defaults['_controller'][0]);
$this->assertEquals($new_defaults['_controller'][1], 'getContentResult');
$this->assertEquals('controller.entity_form:getContentResult', $new_defaults['_controller']);
// Set _entity_list and ensure that the entity list controller is set.
$defaults = array();