summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Pott2014-05-23 12:29:20 (GMT)
committerAlex Pott2014-05-23 12:29:20 (GMT)
commit15cf730ddef00c2b300778782acd4de170d40225 (patch)
treedcaf08ef375ae3f3a7aaffbd6228f8ac00688bd5
parent4eeda371cffc456ac5d8bf9470a45de70b4130cb (diff)
Issue #2165475 by damiankloip, dawehner, martin107, tim.plunkett, jibran, xjm, Jalandhar: Provide a generic class resolver.
-rw-r--r--core/core.services.yml15
-rw-r--r--core/lib/Drupal/Core/Controller/ControllerResolver.php42
-rw-r--r--core/lib/Drupal/Core/Controller/FormController.php11
-rw-r--r--core/lib/Drupal/Core/Controller/HtmlFormController.php26
-rw-r--r--core/lib/Drupal/Core/DependencyInjection/ClassResolver.php47
-rw-r--r--core/lib/Drupal/Core/DependencyInjection/ClassResolverInterface.php31
-rw-r--r--core/lib/Drupal/Core/Entity/EntityManager.php21
-rw-r--r--core/lib/Drupal/Core/EventSubscriber/ContentFormControllerSubscriber.php18
-rw-r--r--core/lib/Drupal/Core/Form/FormBuilder.php24
-rw-r--r--core/modules/views/lib/Drupal/views/Form/ViewsForm.php27
-rw-r--r--core/modules/views/views.theme.inc2
-rw-r--r--core/tests/Drupal/Tests/Core/Controller/ControllerResolverTest.php6
-rw-r--r--core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php19
-rw-r--r--core/tests/Drupal/Tests/Core/Form/FormTestBase.php40
-rw-r--r--core/tests/Drupal/Tests/Core/HttpKernelTest.php6
-rw-r--r--core/tests/Drupal/Tests/UnitTestCase.php21
16 files changed, 252 insertions, 104 deletions
diff --git a/core/core.services.yml b/core/core.services.yml
index c4b55ac..0543272 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -121,7 +121,7 @@ services:
arguments: [default]
form_builder:
class: Drupal\Core\Form\FormBuilder
- arguments: ['@form_validator', '@form_submitter', '@module_handler', '@keyvalue.expirable', '@event_dispatcher', '@request_stack', '@?csrf_token', '@?http_kernel']
+ arguments: ['@form_validator', '@form_submitter', '@module_handler', '@keyvalue.expirable', '@event_dispatcher', '@request_stack', '@class_resolver', '@?csrf_token', '@?http_kernel']
form_validator:
class: Drupal\Core\Form\FormValidator
arguments: ['@request_stack', '@string_translation', '@csrf_token']
@@ -224,7 +224,7 @@ services:
arguments: ['@config.factory', '@module_handler', '@state', '@info_parser', '@config.installer', '@router.builder']
entity.manager:
class: Drupal\Core\Entity\EntityManager
- arguments: ['@container.namespaces', '@module_handler', '@cache.discovery', '@language_manager', '@string_translation']
+ arguments: ['@container.namespaces', '@module_handler', '@cache.discovery', '@language_manager', '@string_translation', '@class_resolver']
parent: container.trait
tags:
- { name: plugin_manager_cache_clear }
@@ -270,8 +270,11 @@ services:
arguments: ['@service_container']
controller_resolver:
class: Drupal\Core\Controller\ControllerResolver
- arguments: ['@logger.channel.default']
- parent: container.trait
+ arguments: ['@class_resolver', '@logger.channel.default']
+ class_resolver:
+ class: Drupal\Core\DependencyInjection\ClassResolver
+ calls:
+ - [setContainer, ['@service_container']]
title_resolver:
class: Drupal\Core\Controller\TitleResolver
arguments: ['@controller_resolver', '@string_translation']
@@ -476,7 +479,7 @@ services:
- { name: event_subscriber }
route_content_form_controller_subscriber:
class: Drupal\Core\EventSubscriber\ContentFormControllerSubscriber
- arguments: ['@controller_resolver', '@form_builder']
+ arguments: ['@class_resolver', '@controller_resolver', '@form_builder']
parent: container.trait
tags:
- { name: event_subscriber }
@@ -496,7 +499,7 @@ services:
arguments: ['@controller_resolver', '@ajax_response_renderer']
controller.entityform:
class: Drupal\Core\Entity\HtmlEntityFormController
- arguments: ['@controller_resolver', '@service_container', '@entity.manager']
+ arguments: ['@class_resolver', '@controller_resolver', '@service_container', '@entity.manager']
controller.dialog:
class: Drupal\Core\Controller\DialogController
arguments: ['@controller_resolver', '@title_resolver']
diff --git a/core/lib/Drupal/Core/Controller/ControllerResolver.php b/core/lib/Drupal/Core/Controller/ControllerResolver.php
index c80242c..f165018 100644
--- a/core/lib/Drupal/Core/Controller/ControllerResolver.php
+++ b/core/lib/Drupal/Core/Controller/ControllerResolver.php
@@ -10,8 +10,7 @@ namespace Drupal\Core\Controller;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ControllerResolver as BaseControllerResolver;
-use Symfony\Component\DependencyInjection\ContainerAwareInterface;
-use Symfony\Component\DependencyInjection\ContainerAwareTrait;
+use Drupal\Core\DependencyInjection\ClassResolverInterface;
/**
* ControllerResolver to enhance controllers beyond Symfony's basic handling.
@@ -28,9 +27,7 @@ use Symfony\Component\DependencyInjection\ContainerAwareTrait;
* controller by using a service:method notation (Symfony uses the same
* convention).
*/
-class ControllerResolver extends BaseControllerResolver implements ControllerResolverInterface, ContainerAwareInterface {
-
- use ContainerAwareTrait;
+class ControllerResolver extends BaseControllerResolver implements ControllerResolverInterface {
/**
* The PSR-3 logger. (optional)
@@ -40,12 +37,23 @@ class ControllerResolver extends BaseControllerResolver implements ControllerRes
protected $logger;
/**
+ * The class resolver.
+ *
+ * @var \Drupal\Core\DependencyInjection\ClassResolverInterface
+ */
+ protected $classResolver;
+
+ /**
* Constructs a new ControllerResolver.
*
+ * @param \Drupal\Core\DependencyInjection\ClassResolverInterface $class_resolver
+ * The class resolver.
* @param \Psr\Log\LoggerInterface $logger
* (optional) A LoggerInterface instance.
*/
- public function __construct(LoggerInterface $logger = NULL) {
+ public function __construct(ClassResolverInterface $class_resolver, LoggerInterface $logger = NULL) {
+ $this->classResolver = $class_resolver;
+
parent::__construct($logger);
}
@@ -109,31 +117,17 @@ class ControllerResolver extends BaseControllerResolver implements ControllerRes
// Controller in the service:method notation.
$count = substr_count($controller, ':');
if ($count == 1) {
- list($service, $method) = explode(':', $controller, 2);
- return array($this->container->get($service), $method);
+ list($class_or_service, $method) = explode(':', $controller, 2);
}
-
// Controller in the class::method notation.
- if (strpos($controller, '::') !== FALSE) {
- list($class, $method) = explode('::', $controller, 2);
- if (!class_exists($class)) {
- throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class));
- }
- // @todo Remove the second in_array() once that interface has been removed.
- if (in_array('Drupal\Core\DependencyInjection\ContainerInjectionInterface', class_implements($class))) {
- $controller = $class::create($this->container);
- }
- else {
- $controller = new $class();
- }
+ elseif (strpos($controller, '::') !== FALSE) {
+ list($class_or_service, $method) = explode('::', $controller, 2);
}
else {
throw new \LogicException(sprintf('Unable to parse the controller name "%s".', $controller));
}
- if ($controller instanceof ContainerAwareInterface) {
- $controller->setContainer($this->container);
- }
+ $controller = $this->classResolver->getInstanceFromDefinition($class_or_service);
return array($controller, $method);
}
diff --git a/core/lib/Drupal/Core/Controller/FormController.php b/core/lib/Drupal/Core/Controller/FormController.php
index 5296a4b..5fec415 100644
--- a/core/lib/Drupal/Core/Controller/FormController.php
+++ b/core/lib/Drupal/Core/Controller/FormController.php
@@ -8,6 +8,7 @@
namespace Drupal\Core\Controller;
use Drupal\Core\DependencyInjection\DependencySerialization;
+use Drupal\Core\Controller\ControllerResolverInterface;
use Drupal\Core\Form\FormBuilderInterface;
use Symfony\Component\HttpFoundation\Request;
@@ -30,7 +31,7 @@ abstract class FormController extends DependencySerialization {
*
* @var \Drupal\Core\Controller\ControllerResolverInterface
*/
- protected $resolver;
+ protected $controllerResolver;
/**
* The form builder.
@@ -42,13 +43,13 @@ abstract class FormController extends DependencySerialization {
/**
* Constructs a new \Drupal\Core\Controller\FormController object.
*
- * @param \Drupal\Core\Controller\ControllerResolverInterface $resolver
+ * @param \Drupal\Core\Controller\ControllerResolverInterface $controller_resolver
* The controller resolver.
* @param \Drupal\Core\Form\FormBuilderInterface $form_builder
* The form builder.
*/
- public function __construct(ControllerResolverInterface $resolver, FormBuilderInterface $form_builder) {
- $this->resolver = $resolver;
+ public function __construct(ControllerResolverInterface $controller_resolver, FormBuilderInterface $form_builder) {
+ $this->controllerResolver = $controller_resolver;
$this->formBuilder = $form_builder;
}
@@ -69,7 +70,7 @@ abstract class FormController extends DependencySerialization {
$form_state = array();
$request->attributes->set('form', array());
$request->attributes->set('form_state', $form_state);
- $args = $this->resolver->getArguments($request, array($form_object, 'buildForm'));
+ $args = $this->controllerResolver->getArguments($request, array($form_object, 'buildForm'));
$request->attributes->remove('form');
$request->attributes->remove('form_state');
diff --git a/core/lib/Drupal/Core/Controller/HtmlFormController.php b/core/lib/Drupal/Core/Controller/HtmlFormController.php
index 2e92c80..c7525b1 100644
--- a/core/lib/Drupal/Core/Controller/HtmlFormController.php
+++ b/core/lib/Drupal/Core/Controller/HtmlFormController.php
@@ -10,6 +10,8 @@ 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.
@@ -31,10 +33,18 @@ class HtmlFormController extends FormController {
protected $formClass;
/**
+ * The class resolver.
+ *
+ * @var \Drupal\Core\DependencyInjection\ClassResolverInterface;
+ */
+ protected $classResolver;
+
+ /**
* Constructs a new \Drupal\Core\Routing\Enhancer\FormEnhancer object.
*/
- public function __construct(ControllerResolverInterface $resolver, ContainerInterface $container, $class, FormBuilderInterface $form_builder) {
- parent::__construct($resolver, $form_builder);
+ public function __construct(ClassResolverInterface $class_resolver, ControllerResolverInterface $controller_resolver, ContainerInterface $container, $class, FormBuilderInterface $form_builder) {
+ parent::__construct($controller_resolver, $form_builder);
+ $this->classResolver = $class_resolver;
$this->container = $container;
$this->formDefinition = $class;
}
@@ -51,17 +61,7 @@ class HtmlFormController extends FormController {
* The form object to use.
*/
protected function getFormObject(Request $request, $form_arg) {
- // If this is a class, instantiate it.
- if (class_exists($form_arg)) {
- if (in_array('Drupal\Core\DependencyInjection\ContainerInjectionInterface', class_implements($form_arg))) {
- return $form_arg::create($this->container);
- }
-
- return new $form_arg();
- }
-
- // Otherwise, it is a service.
- return $this->container->get($form_arg);
+ return $this->classResolver->getInstanceFromDefinition($form_arg);
}
}
diff --git a/core/lib/Drupal/Core/DependencyInjection/ClassResolver.php b/core/lib/Drupal/Core/DependencyInjection/ClassResolver.php
new file mode 100644
index 0000000..997630d
--- /dev/null
+++ b/core/lib/Drupal/Core/DependencyInjection/ClassResolver.php
@@ -0,0 +1,47 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\DependencyInjection\ClassResolver.
+ */
+
+namespace Drupal\Core\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\ContainerAwareTrait;
+use Symfony\Component\DependencyInjection\ContainerAwareInterface;
+
+/**
+ * Implements the class resolver interface supporting class names and services.
+ */
+class ClassResolver implements ClassResolverInterface, ContainerAwareInterface {
+
+ use ContainerAwareTrait;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getInstanceFromDefinition($definition) {
+ if ($this->container->has($definition)) {
+ $instance = $this->container->get($definition);
+ }
+ else {
+ if (!class_exists($definition)) {
+ throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $definition));
+ }
+
+ if (is_subclass_of($definition, 'Drupal\Core\DependencyInjection\ContainerInjectionInterface')) {
+ $instance = $definition::create($this->container);
+ }
+ else {
+ $instance = new $definition();
+ }
+ }
+
+ if ($instance instanceof ContainerAwareInterface) {
+ $instance->setContainer($this->container);
+ }
+
+ return $instance;
+ }
+
+}
diff --git a/core/lib/Drupal/Core/DependencyInjection/ClassResolverInterface.php b/core/lib/Drupal/Core/DependencyInjection/ClassResolverInterface.php
new file mode 100644
index 0000000..7acfec1
--- /dev/null
+++ b/core/lib/Drupal/Core/DependencyInjection/ClassResolverInterface.php
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\DependencyInjection\ClassResolverInterface.
+ */
+
+namespace Drupal\Core\DependencyInjection;
+
+/**
+ * Provides an interface to get a instance of a class with dependency injection.
+ */
+interface ClassResolverInterface {
+
+ /**
+ * Returns a class instance with a given class definition.
+ *
+ * In contrast to controllers you don't specify a method.
+ *
+ * @param string $definition
+ * A class name or service name.
+ *
+ * @throws \InvalidArgumentException
+ * If $class is not a valid service identifer and the class does not exist.
+ *
+ * @return object
+ * The instance of the class.
+ */
+ public function getInstanceFromDefinition($definition);
+
+}
diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php
index 87e529e..32c9aae 100644
--- a/core/lib/Drupal/Core/Entity/EntityManager.php
+++ b/core/lib/Drupal/Core/Entity/EntityManager.php
@@ -10,6 +10,7 @@ namespace Drupal\Core\Entity;
use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException;
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\Component\Utility\String;
+use Drupal\Core\DependencyInjection\ClassResolverInterface;
use Drupal\Core\Field\FieldDefinition;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheBackendInterface;
@@ -88,6 +89,13 @@ class EntityManager extends DefaultPluginManager implements EntityManagerInterfa
protected $translationManager;
/**
+ * The class resolver.
+ *
+ * @var \Drupal\Core\DependencyInjection\ClassResolverInterface
+ */
+ protected $classResolver;
+
+ /**
* Static cache of bundle information.
*
* @var array
@@ -125,14 +133,17 @@ class EntityManager extends DefaultPluginManager implements EntityManagerInterfa
* The language manager.
* @param \Drupal\Core\StringTranslation\TranslationInterface $translation_manager
* The string translationManager.
+ * @param \Drupal\Core\DependencyInjection\ClassResolverInterface $class_resolver
+ * The class resolver.
*/
- public function __construct(\Traversable $namespaces, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache, LanguageManagerInterface $language_manager, TranslationInterface $translation_manager) {
+ public function __construct(\Traversable $namespaces, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache, LanguageManagerInterface $language_manager, TranslationInterface $translation_manager, ClassResolverInterface $class_resolver) {
parent::__construct('Entity', $namespaces, $module_handler, 'Drupal\Core\Entity\Annotation\EntityType');
$this->setCacheBackend($cache, $language_manager, 'entity_type:', array('entity_types' => TRUE));
$this->alterInfo('entity_type');
$this->translationManager = $translation_manager;
+ $this->classResolver = $class_resolver;
}
/**
@@ -213,12 +224,8 @@ class EntityManager extends DefaultPluginManager implements EntityManagerInterfa
if (!$class = $this->getDefinition($entity_type, TRUE)->getFormClass($operation)) {
throw new InvalidPluginDefinitionException($entity_type, sprintf('The "%s" entity type did not specify a "%s" form class.', $entity_type, $operation));
}
- if (in_array('Drupal\Core\DependencyInjection\ContainerInjectionInterface', class_implements($class))) {
- $controller = $class::create($this->container);
- }
- else {
- $controller = new $class();
- }
+
+ $controller = $this->classResolver->getInstanceFromDefinition($class);
$controller
->setStringTranslation($this->translationManager)
diff --git a/core/lib/Drupal/Core/EventSubscriber/ContentFormControllerSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/ContentFormControllerSubscriber.php
index b64e6a4..4f84925 100644
--- a/core/lib/Drupal/Core/EventSubscriber/ContentFormControllerSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/ContentFormControllerSubscriber.php
@@ -8,6 +8,7 @@
namespace Drupal\Core\EventSubscriber;
use Drupal\Core\Controller\HtmlFormController;
+use Drupal\Core\DependencyInjection\ClassResolverInterface;
use Drupal\Core\Controller\ControllerResolverInterface;
use Drupal\Core\Form\FormBuilderInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
@@ -26,9 +27,9 @@ class ContentFormControllerSubscriber implements EventSubscriberInterface, Conta
/**
* The controller resolver.
*
- * @var \Drupal\Core\Controller\ControllerResolverInterface
+ * @var \Drupal\Core\DependencyInjection\ClassResolverInterface.
*/
- protected $resolver;
+ protected $classResolver;
/**
* The form builder.
@@ -40,13 +41,16 @@ class ContentFormControllerSubscriber implements EventSubscriberInterface, Conta
/**
* Constructs a new ContentFormControllerSubscriber object.
*
- * @param \Drupal\Core\Controller\ControllerResolverInterface $resolver
- * The controller resolver.
+ * @param \Drupal\Core\DependencyInjection\ClassResolverInterface $class_resolver
+ * The class resolver.
+ * @param \Drupal\Core\Controller\ControllerResolverInterface $controller_resolver
+ * The class resolver.
* @param \Drupal\Core\Form\FormBuilderInterface $form_builder
* The form builder.
*/
- public function __construct(ControllerResolverInterface $resolver, FormBuilderInterface $form_builder) {
- $this->resolver = $resolver;
+ public function __construct(ClassResolverInterface $class_resolver, ControllerResolverInterface $controller_resolver, FormBuilderInterface $form_builder) {
+ $this->classResolver = $class_resolver;
+ $this->controllerResolver = $controller_resolver;
$this->formBuilder = $form_builder;
}
@@ -60,7 +64,7 @@ class ContentFormControllerSubscriber implements EventSubscriberInterface, Conta
$request = $event->getRequest();
if ($form = $request->attributes->get('_form')) {
- $wrapper = new HtmlFormController($this->resolver, $this->container, $form, $this->formBuilder);
+ $wrapper = new HtmlFormController($this->classResolver, $this->controllerResolver, $this->container, $form, $this->formBuilder);
$request->attributes->set('_content', array($wrapper, 'getContentResult'));
}
}
diff --git a/core/lib/Drupal/Core/Form/FormBuilder.php b/core/lib/Drupal/Core/Form/FormBuilder.php
index ebaf19b..d3bedc1 100644
--- a/core/lib/Drupal/Core/Form/FormBuilder.php
+++ b/core/lib/Drupal/Core/Form/FormBuilder.php
@@ -11,6 +11,7 @@ use Drupal\Component\Utility\Crypt;
use Drupal\Component\Utility\NestedArray;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Access\CsrfTokenGenerator;
+use Drupal\Core\DependencyInjection\ClassResolverInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\HttpKernel;
use Drupal\Core\KeyValueStore\KeyValueExpirableFactoryInterface;
@@ -71,6 +72,13 @@ class FormBuilder implements FormBuilderInterface, FormValidatorInterface, FormS
protected $httpKernel;
/**
+ * The class resolver.
+ *
+ * @var \Drupal\Core\DependencyInjection\ClassResolverInterface
+ */
+ protected $classResolver;
+
+ /**
* The current user.
*
* @var \Drupal\Core\Session\AccountInterface
@@ -102,18 +110,21 @@ class FormBuilder implements FormBuilderInterface, FormValidatorInterface, FormS
* The event dispatcher.
* @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
* The request stack.
+ * @param \Drupal\Core\DependencyInjection\ClassResolverInterface $class_resolver
+ * The class resolver.
* @param \Drupal\Core\Access\CsrfTokenGenerator $csrf_token
* The CSRF token generator.
* @param \Drupal\Core\HttpKernel $http_kernel
* The HTTP kernel.
*/
- public function __construct(FormValidatorInterface $form_validator, FormSubmitterInterface $form_submitter, ModuleHandlerInterface $module_handler, KeyValueExpirableFactoryInterface $key_value_expirable_factory, EventDispatcherInterface $event_dispatcher, RequestStack $request_stack, CsrfTokenGenerator $csrf_token = NULL, HttpKernel $http_kernel = NULL) {
+ public function __construct(FormValidatorInterface $form_validator, FormSubmitterInterface $form_submitter, ModuleHandlerInterface $module_handler, KeyValueExpirableFactoryInterface $key_value_expirable_factory, EventDispatcherInterface $event_dispatcher, RequestStack $request_stack, ClassResolverInterface $class_resolver, CsrfTokenGenerator $csrf_token = NULL, HttpKernel $http_kernel = NULL) {
$this->formValidator = $form_validator;
$this->formSubmitter = $form_submitter;
$this->moduleHandler = $module_handler;
$this->keyValueExpirableFactory = $key_value_expirable_factory;
$this->eventDispatcher = $event_dispatcher;
$this->requestStack = $request_stack;
+ $this->classResolver = $class_resolver;
$this->csrfToken = $csrf_token;
$this->httpKernel = $http_kernel;
}
@@ -122,15 +133,12 @@ class FormBuilder implements FormBuilderInterface, FormValidatorInterface, FormS
* {@inheritdoc}
*/
public function getFormId($form_arg, &$form_state) {
- // If the $form_arg is the name of a class, instantiate it.
+ // If the $form_arg is the name of a class, instantiate it. Don't allow
+ // arbitrary strings to be passed to the class resolver.
if (is_string($form_arg) && class_exists($form_arg)) {
- if (in_array('Drupal\Core\DependencyInjection\ContainerInjectionInterface', class_implements($form_arg))) {
- $form_arg = $form_arg::create(\Drupal::getContainer());
- }
- else {
- $form_arg = new $form_arg();
- }
+ $form_arg = $this->classResolver->getInstanceFromDefinition($form_arg);
}
+
// If the $form_arg implements \Drupal\Core\Form\FormInterface, add that as
// the callback object and determine the form ID.
if (is_object($form_arg) && $form_arg instanceof FormInterface) {
diff --git a/core/modules/views/lib/Drupal/views/Form/ViewsForm.php b/core/modules/views/lib/Drupal/views/Form/ViewsForm.php
index cc01f8d..45f1730 100644
--- a/core/modules/views/lib/Drupal/views/Form/ViewsForm.php
+++ b/core/modules/views/lib/Drupal/views/Form/ViewsForm.php
@@ -9,6 +9,7 @@ namespace Drupal\views\Form;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Controller\ControllerResolverInterface;
+use Drupal\Core\DependencyInjection\ClassResolverInterface;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\DependencyInjection\DependencySerialization;
use Drupal\Core\Form\FormInterface;
@@ -28,11 +29,11 @@ use Symfony\Component\HttpFoundation\Request;
class ViewsForm extends DependencySerialization implements FormInterface, ContainerInjectionInterface {
/**
- * The controller resolver to get the subform form objects.
+ * The class resolver to get the subform form objects.
*
- * @var \Drupal\Core\Controller\ControllerResolverInterface
+ * @var \Drupal\Core\DependencyInjection\ClassResolverInterface
*/
- protected $controllerResolver;
+ protected $classResolver;
/**
* The current request.
@@ -65,8 +66,8 @@ class ViewsForm extends DependencySerialization implements FormInterface, Contai
/**
* Constructs a ViewsForm object.
*
- * @param \Drupal\Core\Controller\ControllerResolverInterface $controller_resolver
- * The controller resolver to get the subform form objects.
+ * @param \Drupal\Core\DependencyInjection\ClassResolverInterface $controller_resolver
+ * The class resolver to get the subform form objects.
* @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator
* The url generator to generate the form action.
* @param \Symfony\Component\HttpFoundation\Request $request
@@ -76,8 +77,8 @@ class ViewsForm extends DependencySerialization implements FormInterface, Contai
* @param string $view_display_id
* The ID of the active view's display.
*/
- public function __construct(ControllerResolverInterface $controller_resolver, UrlGeneratorInterface $url_generator, Request $request, $view_id, $view_display_id) {
- $this->controllerResolver = $controller_resolver;
+ public function __construct(ClassResolverInterface $controller_resolver, UrlGeneratorInterface $url_generator, Request $request, $view_id, $view_display_id) {
+ $this->classResolver = $controller_resolver;
$this->urlGenerator = $url_generator;
$this->request = $request;
$this->viewId = $view_id;
@@ -169,17 +170,7 @@ class ViewsForm extends DependencySerialization implements FormInterface, Contai
protected function getFormObject(array $form_state) {
// If this is a class, instantiate it.
$form_step_class = isset($form_state['step_controller'][$form_state['step']]) ? $form_state['step_controller'][$form_state['step']] : 'Drupal\views\Form\ViewsFormMainForm';
- $container = \Drupal::getContainer();
- if (class_exists($form_step_class)) {
- if (in_array('Drupal\Core\DependencyInjection\ContainerInjectionInterface', class_implements($form_step_class))) {
- return $form_step_class::create($container);
- }
-
- return new $form_step_class();
- }
-
- // Otherwise, it is a service.
- return $container->get($form_step_class);
+ return $this->classResolver->getInstanceFromDefinition($form_step_class);
}
}
diff --git a/core/modules/views/views.theme.inc b/core/modules/views/views.theme.inc
index ae967bd..86e3e85 100644
--- a/core/modules/views/views.theme.inc
+++ b/core/modules/views/views.theme.inc
@@ -121,7 +121,7 @@ function template_preprocess_views_view(&$variables) {
}
$container = \Drupal::getContainer();
- $form_object = new ViewsForm($container->get('controller_resolver'), $container->get('url_generator'), $container->get('request'), $view->storage->id(), $view->current_display);
+ $form_object = new ViewsForm($container->get('class_resolver'), $container->get('url_generator'), $container->get('request'), $view->storage->id(), $view->current_display);
$form = \Drupal::formBuilder()->getForm($form_object, $view, $output);
// The form is requesting that all non-essential views elements be hidden,
// usually because the rendered step is not a view result.
diff --git a/core/tests/Drupal/Tests/Core/Controller/ControllerResolverTest.php b/core/tests/Drupal/Tests/Core/Controller/ControllerResolverTest.php
index da201f5..923c94b 100644
--- a/core/tests/Drupal/Tests/Core/Controller/ControllerResolverTest.php
+++ b/core/tests/Drupal/Tests/Core/Controller/ControllerResolverTest.php
@@ -8,6 +8,7 @@
namespace Drupal\Tests\Core\Controller;
use Drupal\Core\Controller\ControllerResolver;
+use Drupal\Core\DependencyInjection\ClassResolver;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Tests\UnitTestCase;
@@ -59,8 +60,9 @@ class ControllerResolverTest extends UnitTestCase {
parent::setUp();
$this->container = new ContainerBuilder();
- $this->controllerResolver = new ControllerResolver();
- $this->controllerResolver->setContainer($this->container);
+ $class_resolver = new ClassResolver();
+ $class_resolver->setContainer($this->container);
+ $this->controllerResolver = new ControllerResolver($class_resolver);
}
/**
diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
index 0056594..677eb18 100644
--- a/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
@@ -81,6 +81,20 @@ class EntityManagerTest extends UnitTestCase {
protected $translationManager;
/**
+ * The form builder.
+ *
+ * @var \Drupal\Core\Form\FormBuilderInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $formBuilder;
+
+ /**
+ * The controller resolver.
+ *
+ * @var \Drupal\Core\Controller\ControllerResolverInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $controllerResolver;
+
+ /**
* {@inheritdoc}
*/
public static function getInfo() {
@@ -115,6 +129,9 @@ class EntityManagerTest extends UnitTestCase {
$this->translationManager = $this->getStringTranslationStub();
+ $this->formBuilder = $this->getMock('Drupal\Core\Form\FormBuilderInterface');
+ $this->controllerResolver = $this->getClassResolverStub();
+
$this->container = $this->getContainerWithCacheBins($this->cache);
$this->discovery = $this->getMock('Drupal\Component\Plugin\Discovery\DiscoveryInterface');
@@ -148,7 +165,7 @@ class EntityManagerTest extends UnitTestCase {
->method('getDefinitions')
->will($this->returnValue($definitions));
- $this->entityManager = new TestEntityManager(new \ArrayObject(), $this->moduleHandler, $this->cache, $this->languageManager, $this->translationManager);
+ $this->entityManager = new TestEntityManager(new \ArrayObject(), $this->moduleHandler, $this->cache, $this->languageManager, $this->translationManager, $this->getClassResolverStub());
$this->entityManager->setContainer($this->container);
$this->entityManager->setDiscovery($this->discovery);
}
diff --git a/core/tests/Drupal/Tests/Core/Form/FormTestBase.php b/core/tests/Drupal/Tests/Core/Form/FormTestBase.php
index 280e54e..640ce98 100644
--- a/core/tests/Drupal/Tests/Core/Form/FormTestBase.php
+++ b/core/tests/Drupal/Tests/Core/Form/FormTestBase.php
@@ -42,42 +42,49 @@ abstract class FormTestBase extends UnitTestCase {
/**
* The mocked URL generator.
*
- * @var \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\Routing\UrlGeneratorInterface
+ * @var \Drupal\Core\Routing\UrlGeneratorInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $urlGenerator;
/**
* The mocked module handler.
*
- * @var \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\Extension\ModuleHandlerInterface
+ * @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $moduleHandler;
/**
* The expirable key value store used by form cache.
*
- * @var \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface
+ * @var \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $formCache;
/**
* The expirable key value store used by form state cache.
*
- * @var \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface
+ * @var \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $formStateCache;
/**
* The current user.
*
- * @var \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\Session\AccountInterface
+ * @var \Drupal\Core\Session\AccountInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $account;
/**
+ * The controller resolver.
+ *
+ * @var \Drupal\Core\Controller\ControllerResolverInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $controllerResolver;
+
+ /**
* The CSRF token generator.
*
- * @var \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\Access\CsrfTokenGenerator
+ * @var \Drupal\Core\Access\CsrfTokenGenerator|\PHPUnit_Framework_MockObject_MockObject
*/
protected $csrfToken;
@@ -96,21 +103,33 @@ abstract class FormTestBase extends UnitTestCase {
protected $requestStack;
/**
+ * The class results.
+ *
+ * @var \Drupal\Core\DependencyInjection\ClassResolverInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $classResolver;
+
+ /**
* The event dispatcher.
*
- * @var \PHPUnit_Framework_MockObject_MockObject|\Symfony\Component\EventDispatcher\EventDispatcherInterface
+ * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $eventDispatcher;
/**
* The expirable key value factory.
*
- * @var \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\KeyValueStore\KeyValueExpirableFactory
+ * @var \Drupal\Core\KeyValueStore\KeyValueExpirableFactory|\PHPUnit_Framework_MockObject_MockObject
*/
protected $keyValueExpirableFactory;
/**
- * @var \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\HttpKernel
+ * @var \Drupal\Core\StringTranslation\TranslationInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $translationManager;
+
+ /**
+ * @var \Drupal\Core\HttpKernel|\PHPUnit_Framework_MockObject_MockObject
*/
protected $httpKernel;
@@ -130,6 +149,7 @@ abstract class FormTestBase extends UnitTestCase {
)));
$this->urlGenerator = $this->getMock('Drupal\Core\Routing\UrlGeneratorInterface');
+ $this->classResolver = $this->getClassResolverStub();
$this->csrfToken = $this->getMockBuilder('Drupal\Core\Access\CsrfTokenGenerator')
->disableOriginalConstructor()
->getMock();
@@ -150,7 +170,7 @@ abstract class FormTestBase extends UnitTestCase {
->setMethods(array('batchGet', 'drupalInstallationAttempted'))
->getMock();
- $this->formBuilder = new TestFormBuilder($this->formValidator, $this->formSubmitter, $this->moduleHandler, $this->keyValueExpirableFactory, $this->eventDispatcher, $this->requestStack, $this->csrfToken, $this->httpKernel);
+ $this->formBuilder = new TestFormBuilder($this->formValidator, $this->formSubmitter, $this->moduleHandler, $this->keyValueExpirableFactory, $this->eventDispatcher, $this->requestStack, $this->classResolver, $this->csrfToken, $this->httpKernel);
$this->formBuilder->setCurrentUser($this->account);
}
diff --git a/core/tests/Drupal/Tests/Core/HttpKernelTest.php b/core/tests/Drupal/Tests/Core/HttpKernelTest.php
index bf712ec..8115ada 100644
--- a/core/tests/Drupal/Tests/Core/HttpKernelTest.php
+++ b/core/tests/Drupal/Tests/Core/HttpKernelTest.php
@@ -8,6 +8,7 @@
namespace Drupal\Tests\Core;
use Drupal\Core\Controller\ControllerResolver;
+use Drupal\Core\DependencyInjection\ClassResolver;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\HttpKernel;
use Drupal\Tests\UnitTestCase;
@@ -46,8 +47,9 @@ class HttpKernelTest extends UnitTestCase {
$container->set('request', $request, 'request');
$dispatcher = new EventDispatcher();
- $controller_resolver = new ControllerResolver();
- $controller_resolver->setContainer($container);
+ $class_resolver = new ClassResolver();
+ $class_resolver->setContainer($container);
+ $controller_resolver = new ControllerResolver($class_resolver);
$http_kernel = new HttpKernel($dispatcher, $controller_resolver);
$http_kernel->setContainer($container);
diff --git a/core/tests/Drupal/Tests/UnitTestCase.php b/core/tests/Drupal/Tests/UnitTestCase.php
index 898f40e..bcefce7 100644
--- a/core/tests/Drupal/Tests/UnitTestCase.php
+++ b/core/tests/Drupal/Tests/UnitTestCase.php
@@ -230,4 +230,25 @@ abstract class UnitTestCase extends \PHPUnit_Framework_TestCase {
return $container;
}
+ /**
+ * Returns a stub class resolver.
+ *
+ * @return \Drupal\Core\DependencyInjection\ClassResolverInterface|\PHPUnit_Framework_MockObject_MockObject
+ * The class resolver stub.
+ */
+ protected function getClassResolverStub() {
+ $class_resolver = $this->getMock('Drupal\Core\DependencyInjection\ClassResolverInterface');
+ $class_resolver->expects($this->any())
+ ->method('getInstanceFromDefinition')
+ ->will($this->returnCallback(function ($class) {
+ if (is_subclass_of($class, 'Drupal\Core\DependencyInjection\ContainerInjectionInterface')) {
+ return $class::create(\Drupal::getContainer());
+ }
+ else {
+ return new $class();
+ }
+ }));
+ return $class_resolver;
+ }
+
}