diff --git a/core/core.services.yml b/core/core.services.yml index 19b0b72..9599ce5 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -122,7 +122,7 @@ services: arguments: [default] form_builder: class: Drupal\Core\Form\FormBuilder - arguments: ['@module_handler', '@keyvalue.expirable', '@event_dispatcher', '@url_generator', '@string_translation', '@?csrf_token', '@?http_kernel'] + arguments: ['@module_handler', '@keyvalue.expirable', '@event_dispatcher', '@url_generator', '@string_translation', '@class_resolver', '@?csrf_token', '@?http_kernel'] calls: - [setRequest, ['@?request=']] keyvalue: @@ -213,7 +213,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 } @@ -259,7 +259,13 @@ services: arguments: ['@service_container'] controller_resolver: class: Drupal\Core\Controller\ControllerResolver - parent: container.trait + arguments: ['@class_resolver'] + calls: + - [setContainer, ['@service_container']] + class_resolver: + class: Drupal\Core\DependencyInjection\ClassResolver + calls: + - [setContainer, ['@service_container']] title_resolver: class: Drupal\Core\Controller\TitleResolver arguments: ['@controller_resolver', '@string_translation'] @@ -464,7 +470,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 } @@ -484,7 +490,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 c37ed83..e992d99 100644 --- a/core/lib/Drupal/Core/Controller/ControllerResolver.php +++ b/core/lib/Drupal/Core/Controller/ControllerResolver.php @@ -7,6 +7,7 @@ namespace Drupal\Core\Controller; +use Drupal\Core\DependencyInjection\ClassResolverInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Controller\ControllerResolver as BaseControllerResolver; use Symfony\Component\HttpKernel\Log\LoggerInterface; @@ -40,12 +41,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 \Symfony\Component\HttpKernel\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 +121,17 @@ protected function createController($controller) { // 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 @@ * * @var \Drupal\Core\Controller\ControllerResolverInterface */ - protected $resolver; + protected $controllerResolver; /** * The form builder. @@ -42,13 +43,13 @@ /** * 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 @@ public function getContentResult(Request $request) { $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..9733e76 100644 --- a/core/lib/Drupal/Core/Controller/HtmlFormController.php +++ b/core/lib/Drupal/Core/Controller/HtmlFormController.php @@ -10,6 +10,8 @@ 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; } @@ -52,16 +62,7 @@ public function __construct(ControllerResolverInterface $resolver, ContainerInte */ 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 @@ +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 @@ +moduleHandler = $module_handler; @@ -157,6 +168,7 @@ public function __construct(\Traversable $namespaces, ModuleHandlerInterface $mo $this->languageManager = $language_manager; $this->namespaces = $namespaces; $this->translationManager = $translation_manager; + $this->classResolver = $class_resolver; $this->discovery = new AnnotatedClassDiscovery('Entity', $namespaces, 'Drupal\Core\Entity\Annotation\EntityType'); $this->discovery = new InfoHookDecorator($this->discovery, 'entity_type_build'); @@ -222,12 +234,7 @@ public function getFormObject($entity_type, $operation) { 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 ->setTranslationManager($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 @@ public function onRequestDeriveFormWrapper(GetResponseEvent $event) { $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 96f06ba..d5f8629 100644 --- a/core/lib/Drupal/Core/Form/FormBuilder.php +++ b/core/lib/Drupal/Core/Form/FormBuilder.php @@ -12,6 +12,7 @@ use Drupal\Component\Utility\Unicode; 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; @@ -69,6 +70,13 @@ class FormBuilder implements FormBuilderInterface { protected $translationManager; /** + * The class resolver. + * + * @var \Drupal\Core\DependencyInjection\ClassResolverInterface + */ + protected $classResolver; + + /** * The current request. * * @var \Symfony\Component\HttpFoundation\Request @@ -125,17 +133,20 @@ class FormBuilder implements FormBuilderInterface { * The URL generator. * @param \Drupal\Core\StringTranslation\TranslationInterface $translation_manager * The translation manager. + * @param \Drupal\Core\DependencyInjection\ClassResolverInterface $class_resolver + * The controller resolver. * @param \Drupal\Core\Access\CsrfTokenGenerator $csrf_token * The CSRF token generator. * @param \Drupal\Core\HttpKernel $http_kernel * The HTTP kernel. */ - public function __construct(ModuleHandlerInterface $module_handler, KeyValueExpirableFactoryInterface $key_value_expirable_factory, EventDispatcherInterface $event_dispatcher, UrlGeneratorInterface $url_generator, TranslationInterface $translation_manager, CsrfTokenGenerator $csrf_token = NULL, HttpKernel $http_kernel = NULL) { + public function __construct(ModuleHandlerInterface $module_handler, KeyValueExpirableFactoryInterface $key_value_expirable_factory, EventDispatcherInterface $event_dispatcher, UrlGeneratorInterface $url_generator, TranslationInterface $translation_manager, ClassResolverInterface $class_resolver, CsrfTokenGenerator $csrf_token = NULL, HttpKernel $http_kernel = NULL) { $this->moduleHandler = $module_handler; $this->keyValueExpirableFactory = $key_value_expirable_factory; $this->eventDispatcher = $event_dispatcher; $this->urlGenerator = $url_generator; $this->translationManager = $translation_manager; + $this->classResolver = $class_resolver; $this->csrfToken = $csrf_token; $this->httpKernel = $http_kernel; } @@ -146,13 +157,9 @@ public function __construct(ModuleHandlerInterface $module_handler, KeyValueExpi public function getFormId($form_arg, &$form_state) { // If the $form_arg is the name of a class, instantiate it. 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..76b9358 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 @@ 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 @@ 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,12 @@ public function submitForm(array &$form, array &$form_state) { 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(); + return $this->classResolver->getInstanceFromDefinition($form_step_class); } // Otherwise, it is a service. - return $container->get($form_step_class); + return \Drupal::getContainer()->get($form_step_class); } } diff --git a/core/modules/views/views.theme.inc b/core/modules/views/views.theme.inc index 7308da8..795ffa6 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..82efeff 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,7 +60,9 @@ protected function setUp() { parent::setUp(); $this->container = new ContainerBuilder(); - $this->controllerResolver = new ControllerResolver(); + $class_resolver = new ClassResolver(); + $class_resolver->setContainer($this->container); + $this->controllerResolver = new ControllerResolver($class_resolver); $this->controllerResolver->setContainer($this->container); } diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php index 080d79f..7f38ff2 100644 --- a/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php @@ -87,6 +87,13 @@ class EntityManagerTest extends UnitTestCase { protected $formBuilder; /** + * The controller resolver. + * + * @var \Drupal\Core\Controller\ControllerResolverInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $controllerResolver; + + /** * {@inheritdoc} */ public static function getInfo() { @@ -121,6 +128,7 @@ protected function setUp() { $this->translationManager = $this->getStringTranslationStub(); $this->formBuilder = $this->getMock('Drupal\Core\Form\FormBuilderInterface'); + $this->controllerResolver = $this->getClassResolverStub(); $this->container = $this->getContainerWithCacheBins($this->cache); @@ -149,7 +157,7 @@ protected function setUpEntityManager($definitions = array()) { ->method('getDefinitions') ->will($this->returnValue($definitions)); - $this->entityManager = new TestEntityManager(new \ArrayObject(), $this->moduleHandler, $this->cache, $this->languageManager, $this->translationManager, $this->formBuilder); + $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 639b48f..ec769ff 100644 --- a/core/tests/Drupal/Tests/Core/Form/FormTestBase.php +++ b/core/tests/Drupal/Tests/Core/Form/FormTestBase.php @@ -31,42 +31,49 @@ /** * 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; @@ -80,24 +87,24 @@ /** * 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\StringTranslation\TranslationInterface + * @var \Drupal\Core\StringTranslation\TranslationInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $translationManager; /** - * @var \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\HttpKernel + * @var \Drupal\Core\HttpKernel|\PHPUnit_Framework_MockObject_MockObject */ protected $httpKernel; @@ -119,6 +126,7 @@ public function setUp() { $this->eventDispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->urlGenerator = $this->getMock('Drupal\Core\Routing\UrlGeneratorInterface'); $this->translationManager = $this->getStringTranslationStub(); + $this->classResolver = $this->getClassResolverStub(); $this->csrfToken = $this->getMockBuilder('Drupal\Core\Access\CsrfTokenGenerator') ->disableOriginalConstructor() ->getMock(); @@ -142,7 +150,7 @@ protected function tearDown() { * Sets up a new form builder object to test. */ protected function setupFormBuilder() { - $this->formBuilder = new TestFormBuilder($this->moduleHandler, $this->keyValueExpirableFactory, $this->eventDispatcher, $this->urlGenerator, $this->translationManager, $this->csrfToken, $this->httpKernel); + $this->formBuilder = new TestFormBuilder($this->moduleHandler, $this->keyValueExpirableFactory, $this->eventDispatcher, $this->urlGenerator, $this->translationManager, $this->classResolver, $this->csrfToken, $this->httpKernel); $this->formBuilder->setRequest($this->request); $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..061c9b7 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,7 +47,9 @@ public function testSetupSubrequest() { $container->set('request', $request, 'request'); $dispatcher = new EventDispatcher(); - $controller_resolver = new ControllerResolver(); + $class_resolver = new ClassResolver(); + $class_resolver->setContainer($container); + $controller_resolver = new ControllerResolver($class_resolver); $controller_resolver->setContainer($container); $http_kernel = new HttpKernel($dispatcher, $controller_resolver); diff --git a/core/tests/Drupal/Tests/UnitTestCase.php b/core/tests/Drupal/Tests/UnitTestCase.php index 898f40e..9ae4341 100644 --- a/core/tests/Drupal/Tests/UnitTestCase.php +++ b/core/tests/Drupal/Tests/UnitTestCase.php @@ -230,4 +230,25 @@ protected function getContainerWithCacheBins(CacheBackendInterface $backend) { 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('getInstanceFromClassName') + ->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; + } + }