diff options
author | Alex Pott | 2014-05-23 12:29:20 (GMT) |
---|---|---|
committer | Alex Pott | 2014-05-23 12:29:20 (GMT) |
commit | 15cf730ddef00c2b300778782acd4de170d40225 (patch) | |
tree | dcaf08ef375ae3f3a7aaffbd6228f8ac00688bd5 | |
parent | 4eeda371cffc456ac5d8bf9470a45de70b4130cb (diff) |
Issue #2165475 by damiankloip, dawehner, martin107, tim.plunkett, jibran, xjm, Jalandhar: Provide a generic class resolver.
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; + } + } |