Commit 13768e80 authored by catch's avatar catch

Issue #2912169 by alexpott, tobiberlin, Berdir, dawehner, grahamC: Inject the...

Issue #2912169 by alexpott, tobiberlin, Berdir, dawehner, grahamC: Inject the argument resolver into HttpKernel::__construct
parent b20aea60
......@@ -640,10 +640,10 @@ services:
arguments: ['@menu.link_tree', '@entity.manager', '@string_translation']
plugin.manager.menu.local_action:
class: Drupal\Core\Menu\LocalActionManager
arguments: ['@controller_resolver', '@request_stack', '@current_route_match', '@router.route_provider', '@module_handler', '@cache.discovery', '@language_manager', '@access_manager', '@current_user']
arguments: ['@http_kernel.controller.argument_resolver', '@request_stack', '@current_route_match', '@router.route_provider', '@module_handler', '@cache.discovery', '@language_manager', '@access_manager', '@current_user']
plugin.manager.menu.local_task:
class: Drupal\Core\Menu\LocalTaskManager
arguments: ['@controller_resolver', '@request_stack', '@current_route_match', '@router.route_provider', '@module_handler', '@cache.discovery', '@language_manager', '@access_manager', '@current_user']
arguments: ['@http_kernel.controller.argument_resolver', '@request_stack', '@current_route_match', '@router.route_provider', '@module_handler', '@cache.discovery', '@language_manager', '@access_manager', '@current_user']
plugin.manager.menu.contextual_link:
class: Drupal\Core\Menu\ContextualLinkManager
arguments: ['@controller_resolver', '@module_handler', '@cache.discovery', '@language_manager', '@access_manager', '@current_user', '@request_stack']
......@@ -708,12 +708,37 @@ services:
- [setContainer, ['@service_container']]
title_resolver:
class: Drupal\Core\Controller\TitleResolver
arguments: ['@controller_resolver', '@string_translation']
arguments: ['@controller_resolver', '@string_translation', '@http_kernel.controller.argument_resolver']
http_kernel:
class: Stack\StackedHttpKernel
http_kernel.basic:
class: Symfony\Component\HttpKernel\HttpKernel
arguments: ['@event_dispatcher', '@controller_resolver', '@request_stack']
arguments: ['@event_dispatcher', '@controller_resolver', '@request_stack', '@http_kernel.controller.argument_resolver']
http_kernel.controller.argument_resolver:
class: Symfony\Component\HttpKernel\Controller\ArgumentResolver
arguments: ['@http_kernel.controller.argument_metadata_factory', ['@argument_resolver.request_attribute', '@argument_resolver.raw_parameter', '@argument_resolver.request', '@argument_resolver.psr7_request', '@argument_resolver.route_match', '@argument_resolver.default']]
http_kernel.controller.argument_metadata_factory:
class: Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory
public: false
argument_resolver.request_attribute:
class: Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver
public: false
argument_resolver.raw_parameter:
class: Drupal\Core\Controller\ArgumentResolver\RawParameterValueResolver
public: false
argument_resolver.request:
class: Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver
public: false
argument_resolver.psr7_request:
class: Drupal\Core\Controller\ArgumentResolver\Psr7RequestValueResolver
arguments: ['@psr7.http_message_factory']
public: false
argument_resolver.route_match:
class: Drupal\Core\Controller\ArgumentResolver\RouteMatchValueResolver
public: false
argument_resolver.default:
class: Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver
public: false
http_middleware.negotiation:
class: Drupal\Core\StackMiddleware\NegotiationMiddleware
tags:
......@@ -1077,10 +1102,10 @@ services:
- { name: render.main_content_renderer, format: drupal_modal }
controller.form:
class: Drupal\Core\Controller\HtmlFormController
arguments: ['@controller_resolver', '@form_builder', '@class_resolver']
arguments: ['@http_kernel.controller.argument_resolver', '@form_builder', '@class_resolver']
controller.entity_form:
class: Drupal\Core\Entity\HtmlEntityFormController
arguments: ['@controller_resolver', '@form_builder', '@entity.manager']
arguments: ['@http_kernel.controller.argument_resolver', '@form_builder', '@entity.manager']
form_ajax_response_builder:
class: Drupal\Core\Form\FormAjaxResponseBuilder
arguments: ['@main_content_renderer.ajax', '@current_route_match']
......@@ -1634,7 +1659,7 @@ services:
arguments: ['@controller_resolver', '@theme.manager', '@plugin.manager.element_info', '@render_placeholder_generator', '@render_cache', '@request_stack', '%renderer.config%']
early_rendering_controller_wrapper_subscriber:
class: Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber
arguments: ['@controller_resolver', '@renderer']
arguments: ['@http_kernel.controller.argument_resolver', '@renderer']
tags:
- { name: event_subscriber }
# Placeholder strategies for rendering placeholders.
......
<?php
namespace Drupal\Core\Controller\ArgumentResolver;
use Psr\Http\Message\ServerRequestInterface;
use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
/**
* Yields a PSR7 request object based on the request object passed along.
*/
final class Psr7RequestValueResolver implements ArgumentValueResolverInterface {
/**
* The PSR-7 converter.
*
* @var \Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface
*/
protected $httpMessageFactory;
/**
* Constructs a new ControllerResolver.
*
* @param \Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface $http_message_factory
* The PSR-7 converter.
*/
public function __construct(HttpMessageFactoryInterface $http_message_factory) {
$this->httpMessageFactory = $http_message_factory;
}
/**
* {@inheritdoc}
*/
public function supports(Request $request, ArgumentMetadata $argument) {
return $argument->getType() == ServerRequestInterface::class;
}
/**
* {@inheritdoc}
*/
public function resolve(Request $request, ArgumentMetadata $argument) {
yield $this->httpMessageFactory->createRequest($request);
}
}
<?php
namespace Drupal\Core\Controller\ArgumentResolver;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
/**
* Yields an argument's value from the request's _raw_variables attribute.
*/
final class RawParameterValueResolver implements ArgumentValueResolverInterface {
/**
* {@inheritdoc}
*/
public function supports(Request $request, ArgumentMetadata $argument) {
return !$argument->isVariadic() && $request->attributes->has('_raw_variables') && array_key_exists($argument->getName(), $request->attributes->get('_raw_variables'));
}
/**
* {@inheritdoc}
*/
public function resolve(Request $request, ArgumentMetadata $argument) {
yield $request->attributes->get('_raw_variables')[$argument->getName()];
}
}
<?php
namespace Drupal\Core\Controller\ArgumentResolver;
use Drupal\Core\Routing\RouteMatch;
use Drupal\Core\Routing\RouteMatchInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
/**
* Yields a RouteMatch object based on the request object passed along.
*/
final class RouteMatchValueResolver implements ArgumentValueResolverInterface {
/**
* {@inheritdoc}
*/
public function supports(Request $request, ArgumentMetadata $argument) {
return $argument->getType() == RouteMatchInterface::class || is_subclass_of($argument->getType(), RouteMatchInterface::class);
}
/**
* {@inheritdoc}
*/
public function resolve(Request $request, ArgumentMetadata $argument) {
yield RouteMatch::createFromRequest($request);
}
}
......@@ -129,6 +129,10 @@ protected function createController($controller) {
* {@inheritdoc}
*/
protected function doGetArguments(Request $request, $controller, array $parameters) {
// Note this duplicates the deprecation message of
// Symfony\Component\HttpKernel\Controller\ControllerResolver::getArguments()
// to ensure it is removed in Drupal 9.
@trigger_error(sprintf('%s is deprecated as of 8.6.0 and will be removed in 9.0. Inject the "http_kernel.controller.argument_resolver" service instead.', __METHOD__, ArgumentResolverInterface::class), E_USER_DEPRECATED);
$attributes = $request->attributes->all();
$raw_parameters = $request->attributes->has('_raw_variables') ? $request->attributes->get('_raw_variables') : [];
$arguments = [];
......
......@@ -7,6 +7,7 @@
use Drupal\Core\Form\FormState;
use Drupal\Core\Routing\RouteMatchInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
/**
* Common base class for form interstitial controllers.
......@@ -16,10 +17,24 @@
abstract class FormController {
use DependencySerializationTrait;
/**
* The argument resolver.
*
* @var \Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface
*/
protected $argumentResolver;
/**
* The controller resolver.
*
* @var \Drupal\Core\Controller\ControllerResolverInterface
*
* @deprecated
* Deprecated property that is only assigned when the 'controller_resolver'
* service is used as the first parameter to FormController::__construct().
*
* @see https://www.drupal.org/node/2959408
* @see \Drupal\Core\Controller\FormController::__construct()
*/
protected $controllerResolver;
......@@ -33,13 +48,17 @@ abstract class FormController {
/**
* Constructs a new \Drupal\Core\Controller\FormController object.
*
* @param \Drupal\Core\Controller\ControllerResolverInterface $controller_resolver
* The controller resolver.
* @param \Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface $argument_resolver
* The argument resolver.
* @param \Drupal\Core\Form\FormBuilderInterface $form_builder
* The form builder.
*/
public function __construct(ControllerResolverInterface $controller_resolver, FormBuilderInterface $form_builder) {
$this->controllerResolver = $controller_resolver;
public function __construct(ArgumentResolverInterface $argument_resolver, FormBuilderInterface $form_builder) {
$this->argumentResolver = $argument_resolver;
if ($argument_resolver instanceof ControllerResolverInterface) {
@trigger_error("Using the 'controller_resolver' service as the first argument is deprecated, use the 'http_kernel.controller.argument_resolver' instead. If your subclass requires the 'controller_resolver' service add it as an additional argument. See https://www.drupal.org/node/2959408.", E_USER_DEPRECATED);
$this->controllerResolver = $argument_resolver;
}
$this->formBuilder = $form_builder;
}
......@@ -63,7 +82,7 @@ public function getContentResult(Request $request, RouteMatchInterface $route_ma
$form_state = new FormState();
$request->attributes->set('form', []);
$request->attributes->set('form_state', $form_state);
$args = $this->controllerResolver->getArguments($request, [$form_object, 'buildForm']);
$args = $this->argumentResolver->getArguments($request, [$form_object, 'buildForm']);
$request->attributes->remove('form');
$request->attributes->remove('form_state');
......
......@@ -5,6 +5,7 @@
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\DependencyInjection\ClassResolverInterface;
use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
/**
* Wrapping controller for forms that serve as the main page body.
......@@ -21,15 +22,15 @@ class HtmlFormController extends FormController {
/**
* Constructs a new \Drupal\Core\Routing\Enhancer\FormEnhancer object.
*
* @param \Drupal\Core\Controller\ControllerResolverInterface $controller_resolver
* The controller resolver.
* @param \Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface $argument_resolver
* The argument resolver.
* @param \Drupal\Core\Form\FormBuilderInterface $form_builder
* The form builder.
* @param \Drupal\Core\DependencyInjection\ClassResolverInterface $class_resolver
* The class resolver.
*/
public function __construct(ControllerResolverInterface $controller_resolver, FormBuilderInterface $form_builder, ClassResolverInterface $class_resolver) {
parent::__construct($controller_resolver, $form_builder);
public function __construct(ArgumentResolverInterface $argument_resolver, FormBuilderInterface $form_builder, ClassResolverInterface $class_resolver) {
parent::__construct($argument_resolver, $form_builder);
$this->classResolver = $class_resolver;
}
......
......@@ -5,6 +5,7 @@
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslationInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
use Symfony\Component\Routing\Route;
/**
......@@ -20,6 +21,13 @@ class TitleResolver implements TitleResolverInterface {
*/
protected $controllerResolver;
/**
* The argument resolver.
*
* @var \Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface
*/
protected $argumentResolver;
/**
* Constructs a TitleResolver instance.
*
......@@ -27,10 +35,13 @@ class TitleResolver implements TitleResolverInterface {
* The controller resolver.
* @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
* The translation manager.
* @param \Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface $argument_resolver
* The argument resolver.
*/
public function __construct(ControllerResolverInterface $controller_resolver, TranslationInterface $string_translation) {
public function __construct(ControllerResolverInterface $controller_resolver, TranslationInterface $string_translation, ArgumentResolverInterface $argument_resolver) {
$this->controllerResolver = $controller_resolver;
$this->stringTranslation = $string_translation;
$this->argumentResolver = $argument_resolver;
}
/**
......@@ -43,7 +54,7 @@ public function getTitle(Request $request, Route $route) {
// trying to use empty values.
if ($callback = $route->getDefault('_title_callback')) {
$callable = $this->controllerResolver->getControllerFromDefinition($callback);
$arguments = $this->controllerResolver->getArguments($request, $callable);
$arguments = $this->argumentResolver->getArguments($request, $callable);
$route_title = call_user_func_array($callable, $arguments);
}
elseif ($title = $route->getDefault('_title')) {
......
......@@ -2,10 +2,10 @@
namespace Drupal\Core\Entity;
use Drupal\Core\Controller\ControllerResolverInterface;
use Drupal\Core\Controller\FormController;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
/**
* Wrapping controller for entity forms that serve as the main page body.
......@@ -22,15 +22,15 @@ class HtmlEntityFormController extends FormController {
/**
* Constructs a new \Drupal\Core\Routing\Enhancer\FormEnhancer object.
*
* @param \Drupal\Core\Controller\ControllerResolverInterface $resolver
* The controller resolver.
* @param \Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface $argument_resolver
* The argument resolver.
* @param \Drupal\Core\Form\FormBuilderInterface $form_builder
* The form builder.
* @param \Drupal\Core\Entity\EntityManagerInterface $manager
* The entity manager.
*/
public function __construct(ControllerResolverInterface $resolver, FormBuilderInterface $form_builder, EntityManagerInterface $manager) {
parent::__construct($resolver, $form_builder);
public function __construct(ArgumentResolverInterface $argument_resolver, FormBuilderInterface $form_builder, EntityManagerInterface $manager) {
parent::__construct($argument_resolver, $form_builder);
$this->entityManager = $manager;
}
......
......@@ -5,12 +5,12 @@
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Cache\CacheableDependencyInterface;
use Drupal\Core\Cache\CacheableResponseInterface;
use Drupal\Core\Controller\ControllerResolverInterface;
use Drupal\Core\Render\AttachmentsInterface;
use Drupal\Core\Render\BubbleableMetadata;
use Drupal\Core\Render\RenderContext;
use Drupal\Core\Render\RendererInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\HttpKernel\KernelEvents;
......@@ -55,11 +55,11 @@
class EarlyRenderingControllerWrapperSubscriber implements EventSubscriberInterface {
/**
* The controller resolver.
* The argument resolver.
*
* @var \Drupal\Core\Controller\ControllerResolverInterface
* @var \Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface
*/
protected $controllerResolver;
protected $argumentResolver;
/**
* The renderer.
......@@ -71,13 +71,13 @@ class EarlyRenderingControllerWrapperSubscriber implements EventSubscriberInterf
/**
* Constructs a new EarlyRenderingControllerWrapperSubscriber instance.
*
* @param \Drupal\Core\Controller\ControllerResolverInterface $controller_resolver
* The controller resolver.
* @param \Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface $argument_resolver
* The argument resolver.
* @param \Drupal\Core\Render\RendererInterface $renderer
* The renderer.
*/
public function __construct(ControllerResolverInterface $controller_resolver, RendererInterface $renderer) {
$this->controllerResolver = $controller_resolver;
public function __construct(ArgumentResolverInterface $argument_resolver, RendererInterface $renderer) {
$this->argumentResolver = $argument_resolver;
$this->renderer = $renderer;
}
......@@ -91,7 +91,7 @@ public function onController(FilterControllerEvent $event) {
$controller = $event->getController();
// See \Symfony\Component\HttpKernel\HttpKernel::handleRaw().
$arguments = $this->controllerResolver->getArguments($event->getRequest(), $controller);
$arguments = $this->argumentResolver->getArguments($event->getRequest(), $controller);
$event->setController(function () use ($controller, $arguments) {
return $this->wrapControllerExecutionInRenderContext($controller, $arguments);
......
......@@ -5,6 +5,7 @@
use Drupal\Core\Access\AccessManagerInterface;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Controller\ControllerResolverInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Plugin\DefaultPluginManager;
......@@ -15,7 +16,7 @@
use Drupal\Core\Routing\RouteProviderInterface;
use Drupal\Core\Url;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
use Drupal\Core\Session\AccountInterface;
/**
......@@ -47,10 +48,25 @@ class LocalActionManager extends DefaultPluginManager implements LocalActionMana
'class' => 'Drupal\Core\Menu\LocalActionDefault',
];
/**
* An argument resolver object.
*
* @var \Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface
*/
protected $argumentResolver;
/**
* A controller resolver object.
*
* @var \Symfony\Component\HttpKernel\Controller\ControllerResolverInterface
*
* @deprecated
* Using the 'controller_resolver' service as the first argument is
* deprecated, use the 'http_kernel.controller.argument_resolver' instead.
* If your subclass requires the 'controller_resolver' service add it as an
* additional argument.
*
* @see https://www.drupal.org/node/2959408
*/
protected $controllerResolver;
......@@ -99,8 +115,8 @@ class LocalActionManager extends DefaultPluginManager implements LocalActionMana
/**
* Constructs a LocalActionManager object.
*
* @param \Symfony\Component\HttpKernel\Controller\ControllerResolverInterface $controller_resolver
* An object to use in introspecting route methods.
* @param \Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface $argument_resolver
* An object to use in resolving route arguments.
* @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
* The request stack.
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
......@@ -118,11 +134,15 @@ class LocalActionManager extends DefaultPluginManager implements LocalActionMana
* @param \Drupal\Core\Session\AccountInterface $account
* The current user.
*/
public function __construct(ControllerResolverInterface $controller_resolver, RequestStack $request_stack, RouteMatchInterface $route_match, RouteProviderInterface $route_provider, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache_backend, LanguageManagerInterface $language_manager, AccessManagerInterface $access_manager, AccountInterface $account) {
public function __construct(ArgumentResolverInterface $argument_resolver, RequestStack $request_stack, RouteMatchInterface $route_match, RouteProviderInterface $route_provider, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache_backend, LanguageManagerInterface $language_manager, AccessManagerInterface $access_manager, AccountInterface $account) {
// Skip calling the parent constructor, since that assumes annotation-based
// discovery.
$this->factory = new ContainerFactory($this, 'Drupal\Core\Menu\LocalActionInterface');
$this->controllerResolver = $controller_resolver;
$this->argumentResolver = $argument_resolver;
if ($argument_resolver instanceof ControllerResolverInterface) {
@trigger_error("Using the 'controller_resolver' service as the first argument is deprecated, use the 'http_kernel.controller.argument_resolver' instead. If your subclass requires the 'controller_resolver' service add it as an additional argument. See https://www.drupal.org/node/2959408.", E_USER_DEPRECATED);
$this->controllerResolver = $argument_resolver;
}
$this->requestStack = $request_stack;
$this->routeMatch = $route_match;
$this->routeProvider = $route_provider;
......@@ -150,7 +170,7 @@ protected function getDiscovery() {
*/
public function getTitle(LocalActionInterface $local_action) {
$controller = [$local_action, 'getTitle'];
$arguments = $this->controllerResolver->getArguments($this->requestStack->getCurrentRequest(), $controller);
$arguments = $this->argumentResolver->getArguments($this->requestStack->getCurrentRequest(), $controller);
return call_user_func_array($controller, $arguments);
}
......
......@@ -20,6 +20,7 @@
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
/**
* Provides the default local task manager using YML as primary definition.
......@@ -50,10 +51,25 @@ class LocalTaskManager extends DefaultPluginManager implements LocalTaskManagerI
'id' => '',
];
/**
* An argument resolver object.
*
* @var \Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface
*/
protected $argumentResolver;
/**
* A controller resolver object.
*
* @var \Drupal\Core\Controller\ControllerResolverInterface
* @var \Symfony\Component\HttpKernel\Controller\ControllerResolverInterface
*
* @deprecated
* Using the 'controller_resolver' service as the first argument is
* deprecated, use the 'http_kernel.controller.argument_resolver' instead.
* If your subclass requires the 'controller_resolver' service add it as an
* additional argument.
*
* @see https://www.drupal.org/node/2959408
*/
protected $controllerResolver;
......@@ -109,8 +125,8 @@ class LocalTaskManager extends DefaultPluginManager implements LocalTaskManagerI
/**
* Constructs a \Drupal\Core\Menu\LocalTaskManager object.
*
* @param \Drupal\Core\Controller\ControllerResolverInterface $controller_resolver
* An object to use in introspecting route methods.
* @param \Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface $argument_resolver
* An object to use in resolving route arguments.
* @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
* The request object to use for building titles and paths for plugin instances.
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
......@@ -128,9 +144,13 @@ class LocalTaskManager extends DefaultPluginManager implements LocalTaskManagerI
* @param \Drupal\Core\Session\AccountInterface $account
* The current user.
*/
public function __construct(ControllerResolverInterface $controller_resolver, RequestStack $request_stack, RouteMatchInterface $route_match, RouteProviderInterface $route_provider, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache, LanguageManagerInterface $language_manager, AccessManagerInterface $access_manager, AccountInterface $account) {
public function __construct(ArgumentResolverInterface $argument_resolver, RequestStack $request_stack, RouteMatchInterface $route_match, RouteProviderInterface $route_provider, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache, LanguageManagerInterface $language_manager, AccessManagerInterface $access_manager, AccountInterface $account) {
$this->factory = new ContainerFactory($this, '\Drupal\Core\Menu\LocalTaskInterface');
$this->controllerResolver = $controller_resolver;
$this->argumentResolver = $argument_resolver;
if ($argument_resolver instanceof ControllerResolverInterface) {
@trigger_error("Using the 'controller_resolver' service as the first argument is deprecated, use the 'http_kernel.controller.argument_resolver' instead. If your subclass requires the 'controller_resolver' service add it as an additional argument. See https://www.drupal.org/node/2959408.", E_USER_DEPRECATED);
$this->controllerResolver = $argument_resolver;
}
$this->requestStack = $request_stack;
$this->routeMatch = $route_match;
$this->routeProvider = $route_provider;
......@@ -170,7 +190,7 @@ public function processDefinition(&$definition, $plugin_id) {
public function getTitle(LocalTaskInterface $local_task) {
$controller = [$local_task, 'getTitle'];
$request = $this->requestStack->getCurrentRequest();
$arguments = $this->controllerResolver->getArguments($request, $controller);
$arguments = $this->argumentResolver->getArguments($request, $controller);
return call_user_func_array($controller, $arguments);
}
......
......@@ -106,7 +106,9 @@ protected function handleRaw(Request $request) {
$this->setupRequestMatch($request);
$arguments = $controller_resolver->getArguments($request, $db_update_controller);
/** @var \Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface $argument_resolver */
$argument_resolver = $container->get('http_kernel.controller.argument_resolver');
$arguments = $argument_resolver->getArguments($request, $db_update_controller);
return call_user_func_array($db_update_controller, $arguments);
}
......
......@@ -72,6 +72,7 @@ protected function setUp() {
* @see \Drupal\Core\Controller\ControllerResolver::doGetArguments()
*
* @group legacy
* @expectedDeprecation Drupal\Core\Controller\ControllerResolver::doGetArguments is deprecated as of 8.6.0 and will be removed in 9.0. Inject the "http_kernel.controller.argument_resolver" service instead.
*/
public function testGetArguments() {
$controller = function (EntityInterface $entity, $user, RouteMatchInterface $route_match, ServerRequestInterface $psr_7) {
......
<?php
namespace Drupal\Tests\Core\Controller;
use Drupal\Core\Controller\ControllerResolver;
use Drupal\Core\Controller\HtmlFormController;
use Drupal\Core\DependencyInjection\ClassResolverInterface;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Tests\UnitTestCase;
/**
* Tests the FormController class.
*
* @group Controller
*/
class FormControllerTest extends UnitTestCase {
/**
* @expectedDeprecation Using the 'controller_resolver' service as the first argument is deprecated, use the 'http_kernel.controller.argument_resolver' instead. If your subclass requires the 'controller_resolver' service add it as an additional argument. See https://www.drupal.org/node/2959408.
* @group legacy
*/
public function testControllerResolverDeprecation() {
$controller_resolver = $this->getMockBuilder(ControllerResolver::class)->disableOriginalConstructor()->getMock();
$form_builder = $this->getMockBuilder(FormBuilderInterface::class)->getMock();
$class_resolver = $this->getMockBuilder(ClassResolverInterface::class)->getMock();
// Use the HtmlFormController as FormController is abstract.
new HtmlFormController($controller_resolver, $form_builder, $class_resolver);
}
}
......@@ -34,6 +34,13 @@ class TitleResolverTest extends UnitTestCase {
*/
protected $translationManager;
/**
* The mocked argument resolver.
*
* @var \Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $argumentResolver;
/**
* The actual tested title resolver.
*
......@@ -44,8 +51,9 @@ class TitleResolverTest extends UnitTestCase {
protected function setUp() {
$this->controllerResolver = $this->getMock('\Drupal\Core\Controller\ControllerResolverInterface');
$this->translationManager = $this->getMock('\Drupal\Core\StringTranslation\TranslationInterface');
$this->argumentResolver = $this->getMock('\Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface');
$this->titleResolver = new TitleResolver($this->controllerResolver, $this->translationManager);
$this->titleResolver = new TitleResolver($this->controllerResolver, $this->translationManager, $this->argumentResolver);
}
/**
......@@ -108,7 +116,7 @@ public function testDynamicTitle() {
->method('getControllerFromDefinition')
->with('Drupal\Tests\Core\Controller\TitleCallback::example')
->will($this->returnValue($callable));
$this->controllerResolver->expects($this->once())
$this->argumentResolver->expects($this->once())
->method('getArguments')
->with($request, $callable)
->will($this->returnValue(['example']));
......
......@@ -13,8 +13,11 @@
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Access\AccessResultForbidden;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Controller\ControllerResolver;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Language\Language;
use Drupal\Core\Menu\LocalActionManager;
use Drupal\Core\Menu\LocalTaskManager;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Routing\RouteProviderInterface;
use Drupal\Core\Session\AccountInterface;
......@@ -22,7 +25,7 @@
use Drupal\Tests\UnitTestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
/**
* @coversDefaultClass \Drupal\Core\Menu\LocalActionManager
......@@ -31,11 +34,11 @@
class LocalActionManagerTest extends UnitTestCase {
/**
* The mocked controller resolver.
* The mocked argument resolver.
*
* @var \Drupal\Core\Controller\ControllerResolverInterface|\PHPUnit_Framework_MockObject_MockObject
* @var \Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $controllerResolver;
protected $argumentResolver;
/**
* The mocked request.
......@@ -104,7 +107,7 @@ class LocalActionManagerTest extends UnitTestCase {
* {@inheritdoc}
*/
protected function setUp() {
$this->controllerResolver = $this->getMock('Drupal\Core\Controller\ControllerResolverInterface');
$this->argumentResolver = $this->getMock('\Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface');
$this->request = $this->getMock('Symfony\Component\HttpFoundation\Request');
$this->routeProvider = $this->getMock('Drupal\Core\Routing\RouteProviderInterface');
$this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
......@@ -120,7 +123,7 @@ protected function setUp() {
$this->factory = $this->getMock('Drupal\Component\Plugin\Factory\FactoryInterface');
$route_match = $this->getMock('Drupal\Core\Routing\RouteMatchInterface');
$this->localActionManager = new TestLocalActionManager($this->controllerResolver, $this->request, $route_match, $this->routeProvider, $this->moduleHandler, $this->cacheBackend, $this->accessManager, $this->account, $this->discovery, $this->factory);
$this->localActionManager = new TestLocalActionManager($this->argumentResolver, $this->request, $route_match, $this->routeProvider, $this->moduleHandler, $this->cacheBackend, $this->accessManager, $this->account, $this->discovery, $this->factory);
}
/**
......@@ -132,7 +135,7 @@ public function testGetTitle() {