diff --git a/core/core.services.yml b/core/core.services.yml index c4b55ac0066d363734a7ca97a48960850ab08297..0543272d334b4e03a830c37c5687753c632c9f34 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 c80242c87f74194d6a3b4261e5e8a847ef350312..f165018400919ddbaab88fee8da4b32634f69a57 100644 --- a/core/lib/Drupal/Core/Controller/ControllerResolver.php +++ b/core/lib/Drupal/Core/Controller/ControllerResolver.php @@ -10,8 +10,7 @@ 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 @@ * 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) @@ -39,13 +36,24 @@ 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 @@ 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 5296a4b23877a3c54c5372782d23abe1384bd7b5..5fec415cbbeece9cfaa57d4777965bb3dc3c42d6 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 @@ 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 2e92c800731d531c004bae8509b291f22cfc7589..c7525b1569dd977dde0b0f4295a1e23207575585 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. @@ -30,11 +32,19 @@ 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 @@ public function __construct(ControllerResolverInterface $resolver, ContainerInte * 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 0000000000000000000000000000000000000000..997630ddf1af6ba2d9a9107d0cd6c45b1df8ecb4 --- /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 0000000000000000000000000000000000000000..7acfec10eb485eafe0a3222a977b440260643b39 --- /dev/null +++ b/core/lib/Drupal/Core/DependencyInjection/ClassResolverInterface.php @@ -0,0 +1,31 @@ +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 @@ 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 ->setStringTranslation($this->translationManager) diff --git a/core/lib/Drupal/Core/EventSubscriber/ContentFormControllerSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/ContentFormControllerSubscriber.php index b64e6a4b859271153bd7fe72079e7b552fd59b48..4f849258fc62142d6b670020345972ef03789698 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 ebaf19b14261f214f5c32d6c1e0384394725ec12..d3bedc13f8fc663c326d6588d3edfef1fd9be165 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\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; @@ -70,6 +71,13 @@ class FormBuilder implements FormBuilderInterface, FormValidatorInterface, FormS */ protected $httpKernel; + /** + * The class resolver. + * + * @var \Drupal\Core\DependencyInjection\ClassResolverInterface + */ + protected $classResolver; + /** * The current user. * @@ -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 @@ public function __construct(FormValidatorInterface $form_validator, FormSubmitte * {@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 cc01f8d867ab6effe10897863704aae7c3bae67d..45f1730e3cb8c530897ca39c6283c842f419c8b0 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,7 @@ 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(); - } - - // 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 ae967bdb776032951e4e0bd64f43082e304aa8d2..86e3e85745093f3091dcacdfcdead152017d11e2 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 da201f57d90f871f453929eae91d9b52d3879287..923c94b8e35bb96701eeabe73a99d0df354f4a42 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 @@ protected function setUp() { 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 005659443ab033045d4c524dd29108c83f287e06..677eb189cf9cc5352fc298581522ea62b854ac0e 100644 --- a/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php @@ -80,6 +80,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} */ @@ -115,6 +129,9 @@ 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); $this->discovery = $this->getMock('Drupal\Component\Plugin\Discovery\DiscoveryInterface'); @@ -148,7 +165,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->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 280e54ece6cab68b731783d16ec8254dc6e42ef8..640ce98783349db8f9f747812e8045e6138ca87e 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; @@ -95,22 +102,34 @@ 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 @@ public function setUp() { ))); $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 @@ public function setUp() { ->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 bf712ec3ca47b0f462ce19257bc6cd653167546d..8115ada67c1aafdadec8dd770ad58864a57a0632 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 @@ public function testSetupSubrequest() { $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 898f40ef34374f263562cb18eb8fc9032cd74da0..bcefce77d8a82c0fb0e47351fd99415086c68ddc 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('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; + } + }