From 1e08b50f421bdbcb5c5f0bb83ebaff5d3843c3ac Mon Sep 17 00:00:00 2001 From: Alex Pott Date: Fri, 9 Jan 2015 15:14:23 +0000 Subject: [PATCH] Issue #2281619 by dawehner, tim.plunkett: Convert most direct usages within module code of routing related request attributes to use RouteMatchInterface instead --- core/core.services.yml | 2 +- .../Core/Controller/ControllerResolver.php | 19 ++----- core/lib/Drupal/Core/Form/FormBase.php | 19 +++++++ core/lib/Drupal/Core/Routing/AdminContext.php | 31 +++--------- .../Drupal/Core/Routing/CurrentRouteMatch.php | 7 +++ .../Routing/StackedRouteMatchInterface.php | 14 +++++- core/modules/comment/comment.module | 18 +++---- .../src/ConfigEntityMapper.php | 1 + .../src/ConfigMapperInterface.php | 2 + .../ContentTranslationController.php | 31 ++++++------ .../src/Form/ContentTranslationDeleteForm.php | 7 +-- .../Controller/FieldConfigListController.php | 11 +++-- .../field_ui/src/Form/FieldStorageAddForm.php | 2 +- .../Plugin/views/argument_default/Node.php | 42 +++++++++++++++- core/modules/rest/src/RequestHandler.php | 6 ++- core/modules/system/entity.api.php | 8 +-- .../system/src/PathBasedBreadcrumbBuilder.php | 10 ++-- .../src/Controller/EntityTestController.php | 10 ++-- .../src/FormTestControllerObject.php | 5 +- .../src/TestControllers.php | 4 +- .../PathBasedBreadcrumbBuilderTest.php | 4 +- .../src/Plugin/views/argument_default/Tid.php | 43 +++++++++++++++- core/modules/update/update.module | 3 +- .../user/src/Plugin/Block/UserLoginBlock.php | 49 +++++++++++++++++-- .../LanguageNegotiationUserAdmin.php | 20 ++++++-- .../Plugin/views/argument_default/User.php | 45 +++++++++++++++-- .../views/src/Plugin/views/argument/Date.php | 44 ++++++++++++++++- .../views/display/DisplayPluginBase.php | 2 +- .../Controller/ControllerResolverTest.php | 4 +- .../Core/Routing/CurrentRouteMatchTest.php | 34 +++++++++++++ 30 files changed, 383 insertions(+), 114 deletions(-) diff --git a/core/core.services.yml b/core/core.services.yml index 9ab7af7e022..8a5a126e544 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -505,7 +505,7 @@ services: - [fromRequestStack, ['@request_stack']] router.admin_context: class: Drupal\Core\Routing\AdminContext - arguments: ['@request_stack'] + arguments: ['@current_route_match'] router.route_provider: class: Drupal\Core\Routing\RouteProvider arguments: ['@database', '@router.builder', '@state'] diff --git a/core/lib/Drupal/Core/Controller/ControllerResolver.php b/core/lib/Drupal/Core/Controller/ControllerResolver.php index d5193e76541..febffd906ed 100644 --- a/core/lib/Drupal/Core/Controller/ControllerResolver.php +++ b/core/lib/Drupal/Core/Controller/ControllerResolver.php @@ -138,11 +138,15 @@ class ControllerResolver extends BaseControllerResolver implements ControllerRes */ protected function doGetArguments(Request $request, $controller, array $parameters) { $attributes = $request->attributes->all(); + $raw_parameters = $request->attributes->has('_raw_variables') ? $request->attributes->get('_raw_variables') : []; $arguments = array(); foreach ($parameters as $param) { if (array_key_exists($param->name, $attributes)) { $arguments[] = $attributes[$param->name]; } + elseif (array_key_exists($param->name, $raw_parameters)) { + $arguments[] = $attributes[$param->name]; + } elseif ($param->getClass() && $param->getClass()->isInstance($request)) { $arguments[] = $request; } @@ -166,21 +170,6 @@ class ControllerResolver extends BaseControllerResolver implements ControllerRes throw new \RuntimeException(sprintf('Controller "%s" requires that you provide a value for the "$%s" argument (because there is no default value or because there is a non optional argument after this one).', $repr, $param->name)); } } - - // The parameter converter overrides the raw request attributes with the - // upcasted objects. However, it keeps a backup copy of the original, raw - // values in a special request attribute ('_raw_variables'). If a controller - // argument has a type hint, we pass it the upcasted object, otherwise we - // pass it the original, raw value. - if ($request->attributes->has('_raw_variables') && $raw = $request->attributes->get('_raw_variables')->all()) { - foreach ($parameters as $parameter) { - // Use the raw value if a parameter has no typehint. - if (!$parameter->getClass() && isset($raw[$parameter->name])) { - $position = $parameter->getPosition(); - $arguments[$position] = $raw[$parameter->name]; - } - } - } return $arguments; } diff --git a/core/lib/Drupal/Core/Form/FormBase.php b/core/lib/Drupal/Core/Form/FormBase.php index 3a146127930..b60e9ed32cc 100644 --- a/core/lib/Drupal/Core/Form/FormBase.php +++ b/core/lib/Drupal/Core/Form/FormBase.php @@ -53,6 +53,13 @@ abstract class FormBase implements FormInterface, ContainerInjectionInterface { */ protected $loggerFactory; + /** + * The route match. + * + * @var \Drupal\Core\Routing\RouteMatchInterface + */ + protected $routeMatch; + /** * {@inheritdoc} */ @@ -135,6 +142,18 @@ abstract class FormBase implements FormInterface, ContainerInjectionInterface { return $this->requestStack->getCurrentRequest(); } + /** + * Gets the route match. + * + * @return \Drupal\Core\Routing\RouteMatchInterface + */ + protected function getRouteMatch() { + if (!$this->routeMatch) { + $this->routeMatch = \Drupal::routeMatch(); + } + return $this->routeMatch; + } + /** * Sets the request stack object to use. * diff --git a/core/lib/Drupal/Core/Routing/AdminContext.php b/core/lib/Drupal/Core/Routing/AdminContext.php index dac58391552..5ea7c9cce51 100644 --- a/core/lib/Drupal/Core/Routing/AdminContext.php +++ b/core/lib/Drupal/Core/Routing/AdminContext.php @@ -7,8 +7,6 @@ namespace Drupal\Core\Routing; -use Symfony\Cmf\Component\Routing\RouteObjectInterface; -use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Routing\Route; /** @@ -17,20 +15,20 @@ use Symfony\Component\Routing\Route; class AdminContext { /** - * The request stack + * The route match. * - * @var \Symfony\Component\HttpFoundation\RequestStack + * @var \Drupal\Core\Routing\RouteMatchInterface */ - protected $requestStack; + protected $routeMatch; /** * Construct a new admin context helper instance. * - * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack - * The request stack used to determine the current request. + * @param \Drupal\Core\Routing\RouteMatchInterface $route_match + * The route match. */ - public function __construct(RequestStack $request_stack) { - $this->requestStack = $request_stack; + public function __construct(RouteMatchInterface $route_match) { + $this->routeMatch = $route_match; } /** @@ -45,7 +43,7 @@ class AdminContext { */ public function isAdminRoute(Route $route = NULL) { if (!$route) { - $route = $this->getRouteFromRequest(); + $route = $this->routeMatch->getRouteObject(); if (!$route) { return FALSE; } @@ -53,17 +51,4 @@ class AdminContext { return (bool) $route->getOption('_admin_route'); } - /** - * Extract the route object from the request if one is available. - * - * @return \Symfony\Component\Routing\Route - * The route object extracted from the current request. - */ - protected function getRouteFromRequest() { - $request = $this->requestStack->getCurrentRequest(); - if ($request) { - return $request->attributes->get(RouteObjectInterface::ROUTE_OBJECT); - } - } - } diff --git a/core/lib/Drupal/Core/Routing/CurrentRouteMatch.php b/core/lib/Drupal/Core/Routing/CurrentRouteMatch.php index 4b482eaf6b6..979c1891d0f 100644 --- a/core/lib/Drupal/Core/Routing/CurrentRouteMatch.php +++ b/core/lib/Drupal/Core/Routing/CurrentRouteMatch.php @@ -132,4 +132,11 @@ class CurrentRouteMatch implements RouteMatchInterface, StackedRouteMatchInterfa return $this->getRouteMatch($this->requestStack->getParentRequest()); } + /** + * {@inheritdoc} + */ + public function getRouteMatchFromRequest(Request $request) { + return $this->getRouteMatch($request); + } + } diff --git a/core/lib/Drupal/Core/Routing/StackedRouteMatchInterface.php b/core/lib/Drupal/Core/Routing/StackedRouteMatchInterface.php index fde003596ad..e5eb8092906 100644 --- a/core/lib/Drupal/Core/Routing/StackedRouteMatchInterface.php +++ b/core/lib/Drupal/Core/Routing/StackedRouteMatchInterface.php @@ -7,6 +7,8 @@ namespace Drupal\Core\Routing; +use Symfony\Component\HttpFoundation\Request; + /** * Defines an interface for a stack of route matches. * @@ -36,5 +38,15 @@ interface StackedRouteMatchInterface extends RouteMatchInterface { */ public function getParentRouteMatch(); -} + /** + * Returns a route match from a given request, if possible. + * + * @param \Symfony\Component\HttpFoundation\Request + * The request. + * + * @return \Drupal\Core\Routing\RouteMatchInterface|NULL + * THe matching route match, or NULL if there is no matching one. + */ + public function getRouteMatchFromRequest(Request $request); +} diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module index 49785517850..79f0d3860a8 100644 --- a/core/modules/comment/comment.module +++ b/core/modules/comment/comment.module @@ -314,9 +314,9 @@ function comment_view_multiple($comments, $view_mode = 'full', $langcode = NULL) * Implements hook_form_FORM_ID_alter() for field_ui_field_storage_add_form. */ function comment_form_field_ui_field_storage_add_form_alter(&$form, FormStateInterface $form_state) { - $request = \Drupal::request(); - if ($form_state->get('entity_type_id') == 'comment' && $request->attributes->has('commented_entity_type')) { - $form['#title'] = \Drupal::service('comment.manager')->getFieldUIPageTitle($request->attributes->get('commented_entity_type'), $request->attributes->get('field_name')); + $route_match = \Drupal::routeMatch(); + if ($form_state->get('entity_type_id') == 'comment' && $route_match->getParameter('commented_entity_type')) { + $form['#title'] = \Drupal::service('comment.manager')->getFieldUIPageTitle($route_match->getParameter('commented_entity_type'), $route_match->getParameter('field_name')); } if (!_comment_entity_uses_integer_id($form_state->get('entity_type_id'))) { // You cannot use comment fields on entity types with non-integer IDs. @@ -328,9 +328,9 @@ function comment_form_field_ui_field_storage_add_form_alter(&$form, FormStateInt * Implements hook_form_FORM_ID_alter(). */ function comment_form_field_ui_form_display_overview_form_alter(&$form, FormStateInterface $form_state) { - $request = \Drupal::request(); - if ($form['#entity_type'] == 'comment' && $request->attributes->has('commented_entity_type')) { - $form['#title'] = \Drupal::service('comment.manager')->getFieldUIPageTitle($request->attributes->get('commented_entity_type'), $request->attributes->get('field_name')); + $route_match = \Drupal::routeMatch(); + if ($form['#entity_type'] == 'comment' && $route_match->getParameter('commented_entity_type')) { + $form['#title'] = \Drupal::service('comment.manager')->getFieldUIPageTitle($route_match->getParameter('commented_entity_type'), $route_match->getParameter('field_name')); } } @@ -338,9 +338,9 @@ function comment_form_field_ui_form_display_overview_form_alter(&$form, FormStat * Implements hook_form_FORM_ID_alter(). */ function comment_form_field_ui_display_overview_form_alter(&$form, FormStateInterface $form_state) { - $request = \Drupal::request(); - if ($form['#entity_type'] == 'comment' && $request->attributes->has('commented_entity_type')) { - $form['#title'] = \Drupal::service('comment.manager')->getFieldUIPageTitle($request->attributes->get('commented_entity_type'), $request->attributes->get('field_name')); + $route_match = \Drupal::routeMatch(); + if ($form['#entity_type'] == 'comment' && $route_match->getParameter('commented_entity_type')) { + $form['#title'] = \Drupal::service('comment.manager')->getFieldUIPageTitle($route_match->getParameter('commented_entity_type'), $route_match->getParameter('field_name')); } } diff --git a/core/modules/config_translation/src/ConfigEntityMapper.php b/core/modules/config_translation/src/ConfigEntityMapper.php index 2cbc78e38ed..848a6ce2cf6 100644 --- a/core/modules/config_translation/src/ConfigEntityMapper.php +++ b/core/modules/config_translation/src/ConfigEntityMapper.php @@ -11,6 +11,7 @@ use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Config\TypedConfigManagerInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityManagerInterface; +use Drupal\Core\Routing\RouteMatch; use Drupal\Core\Routing\RouteProviderInterface; use Drupal\Core\StringTranslation\TranslationInterface; use Drupal\Core\Url; diff --git a/core/modules/config_translation/src/ConfigMapperInterface.php b/core/modules/config_translation/src/ConfigMapperInterface.php index ba75aa2b629..ac3d531a2ab 100644 --- a/core/modules/config_translation/src/ConfigMapperInterface.php +++ b/core/modules/config_translation/src/ConfigMapperInterface.php @@ -281,6 +281,8 @@ interface ConfigMapperInterface { /** * Populate the config mapper with request data. * + * @todo Replace $request with RouteMatch https://www.drupal.org/node/2295255. + * * @param \Symfony\Component\HttpFoundation\Request $request * Page request object. */ diff --git a/core/modules/content_translation/src/Controller/ContentTranslationController.php b/core/modules/content_translation/src/Controller/ContentTranslationController.php index e3622dc9ddf..dc74210738f 100644 --- a/core/modules/content_translation/src/Controller/ContentTranslationController.php +++ b/core/modules/content_translation/src/Controller/ContentTranslationController.php @@ -10,8 +10,8 @@ namespace Drupal\content_translation\Controller; use Drupal\Core\Controller\ControllerBase; use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Language\LanguageInterface; +use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Url; -use Symfony\Component\HttpFoundation\Request; /** * Base class for entity translation controllers. @@ -37,16 +37,15 @@ class ContentTranslationController extends ControllerBase { /** * Builds the translations overview page. * - * @param \Symfony\Component\HttpFoundation\Request $request - * The request object from which to extract the entity type. + * @param \Drupal\Core\Routing\RouteMatchInterface $route_match + * The route match. * @param string $entity_type_id * (optional) The entity type ID. - * - * @return array - * Array of page elements to render. + * @return array Array of page elements to render. + * Array of page elements to render. */ - public function overview(Request $request, $entity_type_id = NULL) { - $entity = $request->attributes->get($entity_type_id); + public function overview(RouteMatchInterface $route_match, $entity_type_id = NULL) { + $entity = $route_match->getParameter($entity_type_id); $account = $this->currentUser(); $handler = $this->entityManager()->getHandler($entity_type_id, 'translation'); @@ -252,16 +251,16 @@ class ContentTranslationController extends ControllerBase { * @param \Drupal\Core\Language\LanguageInterface $target * The language of the translated values. Defaults to the current content * language. - * @param \Symfony\Component\HttpFoundation\Request $request - * The request object from which to extract the entity type. + * @param \Drupal\Core\Routing\RouteMatchInterface + * The route match object from which to extract the entity type. * @param string $entity_type_id * (optional) The entity type ID. * * @return array * A processed form array ready to be rendered. */ - public function add(LanguageInterface $source, LanguageInterface $target, Request $request, $entity_type_id = NULL) { - $entity = $request->attributes->get($entity_type_id); + public function add(LanguageInterface $source, LanguageInterface $target, RouteMatchInterface $route_match, $entity_type_id = NULL) { + $entity = $route_match->getParameter($entity_type_id); // @todo Exploit the upcoming hook_entity_prepare() when available. // See https://www.drupal.org/node/1810394. @@ -287,16 +286,16 @@ class ContentTranslationController extends ControllerBase { * @param \Drupal\Core\Language\LanguageInterface $language * The language of the translated values. Defaults to the current content * language. - * @param \Symfony\Component\HttpFoundation\Request $request - * The request object from which to extract the entity type. + * @param \Drupal\Core\Routing\RouteMatchInterface + * The route match object from which to extract the entity type. * @param string $entity_type_id * (optional) The entity type ID. * * @return array * A processed form array ready to be rendered. */ - public function edit(LanguageInterface $language, Request $request, $entity_type_id = NULL) { - $entity = $request->attributes->get($entity_type_id); + public function edit(LanguageInterface $language, RouteMatchInterface $route_match, $entity_type_id = NULL) { + $entity = $route_match->getParameter($entity_type_id); // @todo Provide a way to figure out the default form operation. Maybe like // $operation = isset($info['default_operation']) ? $info['default_operation'] : 'default'; diff --git a/core/modules/content_translation/src/Form/ContentTranslationDeleteForm.php b/core/modules/content_translation/src/Form/ContentTranslationDeleteForm.php index b6b16e62bfd..015ae960de8 100644 --- a/core/modules/content_translation/src/Form/ContentTranslationDeleteForm.php +++ b/core/modules/content_translation/src/Form/ContentTranslationDeleteForm.php @@ -9,6 +9,7 @@ namespace Drupal\content_translation\Form; use Drupal\Core\Form\ConfirmFormBase; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Language\LanguageInterface; use Drupal\Core\Url; /** @@ -40,9 +41,9 @@ class ContentTranslationDeleteForm extends ConfirmFormBase { /** * {@inheritdoc} */ - public function buildForm(array $form, FormStateInterface $form_state, $entity_type_id = NULL, $language = NULL) { - $this->entity = $this->getRequest()->attributes->get($entity_type_id); - $this->language = language_load($language); + public function buildForm(array $form, FormStateInterface $form_state, $entity_type_id = NULL, LanguageInterface $language = NULL) { + $this->entity = $this->getRouteMatch()->getParameter($entity_type_id); + $this->language = $language; return parent::buildForm($form, $form_state); } diff --git a/core/modules/field_ui/src/Controller/FieldConfigListController.php b/core/modules/field_ui/src/Controller/FieldConfigListController.php index 8ed9be080c1..4f1a3f0d397 100644 --- a/core/modules/field_ui/src/Controller/FieldConfigListController.php +++ b/core/modules/field_ui/src/Controller/FieldConfigListController.php @@ -8,6 +8,7 @@ namespace Drupal\field_ui\Controller; use Drupal\Core\Entity\Controller\EntityListController; +use Drupal\Core\Routing\RouteMatchInterface; use Symfony\Component\HttpFoundation\Request; /** @@ -22,18 +23,18 @@ class FieldConfigListController extends EntityListController { * The entity type. * @param string $bundle * The entity bundle. - * @param \Symfony\Component\HttpFoundation\Request $request - * The current request. + * @param \Drupal\Core\Routing\RouteMatchInterface $route_match + * The current route match. * * @return array * A render array as expected by drupal_render(). */ - public function listing($entity_type_id = NULL, $bundle = NULL, Request $request = NULL) { + public function listing($entity_type_id = NULL, $bundle = NULL, RouteMatchInterface $route_match = NULL) { if (!$bundle) { $entity_info = $this->entityManager()->getDefinition($entity_type_id); - $bundle = $request->attributes->get('_raw_variables')->get($entity_info->getBundleEntityType()); + $bundle = $route_match->getRawParameter($entity_info->getBundleEntityType()); } - return $this->entityManager()->getListBuilder('field_config')->render($entity_type_id, $bundle, $request); + return $this->entityManager()->getListBuilder('field_config')->render($entity_type_id, $bundle); } } diff --git a/core/modules/field_ui/src/Form/FieldStorageAddForm.php b/core/modules/field_ui/src/Form/FieldStorageAddForm.php index e9f15a7cfe8..f4f2358b4f0 100644 --- a/core/modules/field_ui/src/Form/FieldStorageAddForm.php +++ b/core/modules/field_ui/src/Form/FieldStorageAddForm.php @@ -122,7 +122,7 @@ class FieldStorageAddForm extends FormBase { $form_state->set('entity_type_id', $entity_type_id); } if (!$form_state->get('bundle')) { - $bundle = $bundle ?: $this->getRequest()->attributes->get('_raw_variables')->get($this->bundleEntityTypeId); + $bundle = $bundle ?: $this->getRouteMatch()->getRawParameter($this->bundleEntityTypeId); $form_state->set('bundle', $bundle); } diff --git a/core/modules/node/src/Plugin/views/argument_default/Node.php b/core/modules/node/src/Plugin/views/argument_default/Node.php index f1be8d69b64..3df56fb4e8a 100644 --- a/core/modules/node/src/Plugin/views/argument_default/Node.php +++ b/core/modules/node/src/Plugin/views/argument_default/Node.php @@ -7,9 +7,11 @@ namespace Drupal\node\Plugin\views\argument_default; +use Drupal\Core\Routing\RouteMatchInterface; use Drupal\views\Plugin\CacheablePluginInterface; use Drupal\views\Plugin\views\argument_default\ArgumentDefaultPluginBase; use Drupal\node\NodeInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Default argument plugin to extract a node. @@ -23,11 +25,49 @@ use Drupal\node\NodeInterface; */ class Node extends ArgumentDefaultPluginBase implements CacheablePluginInterface { + /** + * The route match. + * + * @var \Drupal\Core\Routing\RouteMatchInterface + */ + protected $routeMatch; + + /** + * Constructs a new Date instance. + * + * @param array $configuration + * A configuration array containing information about the plugin instance. + * @param string $plugin_id + * The plugin_id for the plugin instance. + * @param mixed $plugin_definition + * The plugin implementation definition. + * + * @param \Drupal\Core\Routing\RouteMatchInterface $route_match + * The route match. + */ + public function __construct(array $configuration, $plugin_id, $plugin_definition, RouteMatchInterface $route_match) { + parent::__construct($configuration, $plugin_id, $plugin_definition); + + $this->routeMatch = $route_match; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('current_route_match') + ); + } + /** * {@inheritdoc} */ public function getArgument() { - if (($node = $this->view->getRequest()->attributes->get('node')) && $node instanceof NodeInterface) { + if (($node = $this->routeMatch->getParameter('node')) && $node instanceof NodeInterface) { return $node->id(); } } diff --git a/core/modules/rest/src/RequestHandler.php b/core/modules/rest/src/RequestHandler.php index c31600d0c8f..0ddfdd72977 100644 --- a/core/modules/rest/src/RequestHandler.php +++ b/core/modules/rest/src/RequestHandler.php @@ -31,11 +31,13 @@ class RequestHandler implements ContainerAwareInterface { * The route match. * @param \Symfony\Component\HttpFoundation\Request $request * The HTTP request object. + * @param \Drupal\Core\Routing\RouteMatchInterface $route_match + * The route match. * * @return \Symfony\Component\HttpFoundation\Response * The response object. */ - public function handle(RouteMatchInterface $route_match, Request $request) { + public function handle(RouteMatchInterface $route_match, Request $request, RouteMatchInterface $route_match) { $plugin = $route_match->getRouteObject()->getDefault('_plugin'); $method = strtolower($request->getMethod()); @@ -76,7 +78,7 @@ class RequestHandler implements ContainerAwareInterface { // Determine the request parameters that should be passed to the resource // plugin. - $route_parameters = $request->attributes->get('_route_params'); + $route_parameters = $route_match->getParameters(); $parameters = array(); // Filter out all internal parameters starting with "_". foreach ($route_parameters as $key => $parameter) { diff --git a/core/modules/system/entity.api.php b/core/modules/system/entity.api.php index 189e8a2c82e..6a970602fc0 100644 --- a/core/modules/system/entity.api.php +++ b/core/modules/system/entity.api.php @@ -893,8 +893,8 @@ function hook_ENTITY_TYPE_storage_load(array $entities) { */ function hook_entity_presave(Drupal\Core\Entity\EntityInterface $entity) { if ($entity instanceof ContentEntityInterface && $entity->isTranslatable()) { - $attributes = \Drupal::request()->attributes; - \Drupal::service('content_translation.synchronizer')->synchronizeFields($entity, $entity->language()->getId(), $attributes->get('source_langcode')); + $route_match = \Drupal::routeMatch(); + \Drupal::service('content_translation.synchronizer')->synchronizeFields($entity, $entity->language()->getId(), $route_match->getParameter('source_langcode')); } } @@ -909,8 +909,8 @@ function hook_entity_presave(Drupal\Core\Entity\EntityInterface $entity) { */ function hook_ENTITY_TYPE_presave(Drupal\Core\Entity\EntityInterface $entity) { if ($entity->isTranslatable()) { - $attributes = \Drupal::request()->attributes; - \Drupal::service('content_translation.synchronizer')->synchronizeFields($entity, $entity->language()->getId(), $attributes->get('source_langcode')); + $route_match = \Drupal::routeMatch(); + \Drupal::service('content_translation.synchronizer')->synchronizeFields($entity, $entity->language()->getId(), $route_match->getParameter('source_langcode')); } } diff --git a/core/modules/system/src/PathBasedBreadcrumbBuilder.php b/core/modules/system/src/PathBasedBreadcrumbBuilder.php index 1075ee7cad8..05693312e10 100644 --- a/core/modules/system/src/PathBasedBreadcrumbBuilder.php +++ b/core/modules/system/src/PathBasedBreadcrumbBuilder.php @@ -14,10 +14,12 @@ use Drupal\Core\Controller\TitleResolverInterface; use Drupal\Core\Link; use Drupal\Core\ParamConverter\ParamNotConvertedException; use Drupal\Core\PathProcessor\InboundPathProcessorInterface; +use Drupal\Core\Routing\RouteMatch; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Component\Utility\Unicode; +use Drupal\Core\Url; use Symfony\Component\HttpFoundation\Request; use Symfony\Cmf\Component\Routing\RouteObjectInterface; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; @@ -139,9 +141,10 @@ class PathBasedBreadcrumbBuilder implements BreadcrumbBuilderInterface { // Copy the path elements for up-casting. $route_request = $this->getRequestForPath(implode('/', $path_elements), $exclude); if ($route_request) { - $access = $this->accessManager->checkRequest($route_request, $this->currentUser); + $route_match = RouteMatch::createFromRequest($route_request); + $access = $this->accessManager->check($route_match, $this->currentUser); if ($access) { - $title = $this->titleResolver->getTitle($route_request, $route_request->attributes->get(RouteObjectInterface::ROUTE_OBJECT)); + $title = $this->titleResolver->getTitle($route_request, $route_match->getRouteObject()); } if ($access) { if (!isset($title)) { @@ -149,7 +152,8 @@ class PathBasedBreadcrumbBuilder implements BreadcrumbBuilderInterface { // route is missing a _title or _title_callback attribute. $title = str_replace(array('-', '_'), ' ', Unicode::ucfirst(end($path_elements))); } - $links[] = Link::createFromRoute($title, $route_request->attributes->get(RouteObjectInterface::ROUTE_NAME), $route_request->attributes->get('_raw_variables')->all()); + $url = Url::fromRouteMatch($route_match); + $links[] = new Link($title, $url); } } diff --git a/core/modules/system/tests/modules/entity_test/src/Controller/EntityTestController.php b/core/modules/system/tests/modules/entity_test/src/Controller/EntityTestController.php index 00619ef25f4..bf5fa29053a 100644 --- a/core/modules/system/tests/modules/entity_test/src/Controller/EntityTestController.php +++ b/core/modules/system/tests/modules/entity_test/src/Controller/EntityTestController.php @@ -10,8 +10,8 @@ namespace Drupal\entity_test\Controller; use Drupal\Core\Cache\Cache; use Drupal\Core\Controller\ControllerBase; use Drupal\Core\Entity\Query\QueryFactory; +use Drupal\Core\Routing\RouteMatchInterface; use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\HttpFoundation\Request; /** * Controller routines for entity_test routes. @@ -65,8 +65,8 @@ class EntityTestController extends ControllerBase { /** * Displays the 'Edit existing entity_test' form. * - * @param \Symfony\Component\HttpFoundation\Request $request - * The request object to get entity type from. + * @param \Drupal\Core\Routing\RouteMatchInterface $route_match + * The route match object to get entity type from. * @param string $entity_type_id * The entity type ID. * @@ -75,8 +75,8 @@ class EntityTestController extends ControllerBase { * * @see \Drupal\entity_test\Routing\EntityTestRoutes::routes() */ - public function testEdit(Request $request, $entity_type_id) { - $entity = $request->attributes->get($entity_type_id); + public function testEdit(RouteMatchInterface $route_match, $entity_type_id) { + $entity = $route_match->getParameter($entity_type_id); $form = $this->entityFormBuilder()->getForm($entity); $form['#title'] = $entity->label(); return $form; diff --git a/core/modules/system/tests/modules/form_test/src/FormTestControllerObject.php b/core/modules/system/tests/modules/form_test/src/FormTestControllerObject.php index a3e50643428..1b96b3da093 100644 --- a/core/modules/system/tests/modules/form_test/src/FormTestControllerObject.php +++ b/core/modules/system/tests/modules/form_test/src/FormTestControllerObject.php @@ -10,6 +10,7 @@ namespace Drupal\form_test; use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\HttpFoundation\Request; /** * Provides a test form object. @@ -34,11 +35,11 @@ class FormTestControllerObject extends FormBase { /** * {@inheritdoc} */ - public function buildForm(array $form, FormStateInterface $form_state, $custom_attributes = NULL) { + public function buildForm(array $form, FormStateInterface $form_state, Request $request = NULL, $custom_attributes = NULL) { $form['element'] = array('#markup' => 'The FormTestControllerObject::buildForm() method was used for this form.'); $form['custom_attribute']['#markup'] = $custom_attributes; - $form['request_attribute']['#markup'] = $this->getRequest()->attributes->get('request_attribute'); + $form['request_attribute']['#markup'] = $request->attributes->get('request_attribute'); $form['bananas'] = array( '#type' => 'textfield', diff --git a/core/modules/system/tests/modules/paramconverter_test/src/TestControllers.php b/core/modules/system/tests/modules/paramconverter_test/src/TestControllers.php index 33f52fcfad9..282261232fc 100644 --- a/core/modules/system/tests/modules/paramconverter_test/src/TestControllers.php +++ b/core/modules/system/tests/modules/paramconverter_test/src/TestControllers.php @@ -9,15 +9,13 @@ namespace Drupal\paramconverter_test; use Drupal\Core\Entity\EntityInterface; use Drupal\node\NodeInterface; -use Symfony\Component\HttpFoundation\Request; /** * Controller routine for testing the paramconverter. */ class TestControllers { - public function testUserNodeFoo(EntityInterface $user, NodeInterface $node, Request $request) { - $foo = $request->attributes->get('foo'); + public function testUserNodeFoo(EntityInterface $user, NodeInterface $node, $foo) { $foo = is_object($foo) ? $foo->label() : $foo; return ['#markup' => "user: {$user->label()}, node: {$node->label()}, foo: $foo"]; } diff --git a/core/modules/system/tests/src/Unit/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php b/core/modules/system/tests/src/Unit/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php index 8ceea8ac9ea..7daf8c2fa9c 100644 --- a/core/modules/system/tests/src/Unit/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php +++ b/core/modules/system/tests/src/Unit/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php @@ -326,8 +326,8 @@ class PathBasedBreadcrumbBuilderTest extends UnitTestCase { */ public function setupAccessManagerToAllow() { $this->accessManager->expects($this->any()) - ->method('checkRequest') - ->will($this->returnValue(AccessResult::allowed())); + ->method('check') + ->willReturn(TRUE); } protected function setupStubPathProcessor() { diff --git a/core/modules/taxonomy/src/Plugin/views/argument_default/Tid.php b/core/modules/taxonomy/src/Plugin/views/argument_default/Tid.php index 2cd7a13430f..a90b5e19305 100644 --- a/core/modules/taxonomy/src/Plugin/views/argument_default/Tid.php +++ b/core/modules/taxonomy/src/Plugin/views/argument_default/Tid.php @@ -8,6 +8,7 @@ namespace Drupal\taxonomy\Plugin\views\argument_default; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Routing\RouteMatchInterface; use Drupal\taxonomy\TermInterface; use Drupal\views\Plugin\CacheablePluginInterface; use Drupal\views\ViewExecutable; @@ -27,6 +28,44 @@ use Symfony\Component\HttpFoundation\Request; */ class Tid extends ArgumentDefaultPluginBase implements CacheablePluginInterface { + /** + * The route match. + * + * @var \Drupal\Core\Routing\RouteMatchInterface + */ + protected $routeMatch; + + /** + * Constructs a new Date instance. + * + * @param array $configuration + * A configuration array containing information about the plugin instance. + * @param string $plugin_id + * The plugin_id for the plugin instance. + * @param mixed $plugin_definition + * The plugin implementation definition. + * + * @param \Drupal\Core\Routing\RouteMatchInterface $route_match + * The route match. + */ + public function __construct(array $configuration, $plugin_id, $plugin_definition, RouteMatchInterface $route_match) { + parent::__construct($configuration, $plugin_id, $plugin_definition); + + $this->routeMatch = $route_match; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('current_route_match') + ); + } + /** * Overrides \Drupal\views\Plugin\views\Plugin\views\PluginBase::init(). */ @@ -126,14 +165,14 @@ class Tid extends ArgumentDefaultPluginBase implements CacheablePluginInterface public function getArgument() { // Load default argument from taxonomy page. if (!empty($this->options['term_page'])) { - if (($taxonomy_term = $this->view->getRequest()->attributes->get('taxonomy_term')) && $taxonomy_term instanceof TermInterface) { + if (($taxonomy_term = $this->routeMatch->getParameter('taxonomy_term')) && $taxonomy_term instanceof TermInterface) { return $taxonomy_term->id(); } } // Load default argument from node. if (!empty($this->options['node'])) { // Just check, if a node could be detected. - if (($node = $this->view->getRequest()->attributes->get('node')) && $node instanceof NodeInterface) { + if (($node = $this->routeMatch->getParameter('node')) && $node instanceof NodeInterface) { $taxonomy = array(); foreach ($node->getFieldDefinitions() as $field) { if ($field->getType() == 'taxonomy_term_reference') { diff --git a/core/modules/update/update.module b/core/modules/update/update.module index a3d92f51772..c4459866196 100644 --- a/core/modules/update/update.module +++ b/core/modules/update/update.module @@ -119,7 +119,8 @@ function update_help($route_name, RouteMatchInterface $route_match) { function update_page_top() { /** @var \Drupal\Core\Routing\AdminContext $admin_context */ $admin_context = \Drupal::service('router.admin_context'); - if ($admin_context->isAdminRoute(\Drupal::request()->attributes->get(RouteObjectInterface::ROUTE_OBJECT)) && \Drupal::currentUser()->hasPermission('administer site configuration')) { + $route_match = \Drupal::routeMatch(); + if ($admin_context->isAdminRoute($route_match->getRouteObject()) && \Drupal::currentUser()->hasPermission('administer site configuration')) { $route_name = \Drupal::routeMatch()->getRouteName(); switch ($route_name) { // These pages don't need additional nagging. diff --git a/core/modules/user/src/Plugin/Block/UserLoginBlock.php b/core/modules/user/src/Plugin/Block/UserLoginBlock.php index 47177a52f4b..9e666768c1f 100644 --- a/core/modules/user/src/Plugin/Block/UserLoginBlock.php +++ b/core/modules/user/src/Plugin/Block/UserLoginBlock.php @@ -7,11 +7,13 @@ namespace Drupal\user\Plugin\Block; +use Drupal\Core\Plugin\ContainerFactoryPluginInterface; +use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Routing\UrlGeneratorTrait; use Drupal\Core\Url; use Drupal\Core\Session\AccountInterface; use Drupal\Core\Block\BlockBase; -use Symfony\Cmf\Component\Routing\RouteObjectInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Provides a 'User login' block. @@ -22,15 +24,56 @@ use Symfony\Cmf\Component\Routing\RouteObjectInterface; * category = @Translation("Forms") * ) */ -class UserLoginBlock extends BlockBase { +class UserLoginBlock extends BlockBase implements ContainerFactoryPluginInterface { use UrlGeneratorTrait; + /** + * The route match. + * + * @var \Drupal\Core\Routing\RouteMatchInterface + */ + protected $routeMatch; + + /** + * Constructs a new UserLoginBlock instance. + * + * @param array $configuration + * The plugin configuration, i.e. an array with configuration values keyed + * by configuration option name. The special key 'context' may be used to + * initialize the defined contexts by setting it to an array of context + * values keyed by context names. + * @param string $plugin_id + * The plugin_id for the plugin instance. + * @param mixed $plugin_definition + * The plugin implementation definition. + * @param \Drupal\Core\Routing\RouteMatchInterface $route_match + * The route match. + */ + public function __construct(array $configuration, $plugin_id, $plugin_definition, RouteMatchInterface $route_match) { + parent::__construct($configuration, $plugin_id, $plugin_definition); + + $this->routeMatch = $route_match; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('current_route_match') + ); + } + + /** * {@inheritdoc} */ protected function blockAccess(AccountInterface $account) { - $route_name = \Drupal::request()->attributes->get(RouteObjectInterface::ROUTE_NAME); + $route_name = $this->routeMatch->getRouteName(); return ($account->isAnonymous() && !in_array($route_name, array('user.register', 'user.login', 'user.logout'))); } diff --git a/core/modules/user/src/Plugin/LanguageNegotiation/LanguageNegotiationUserAdmin.php b/core/modules/user/src/Plugin/LanguageNegotiation/LanguageNegotiationUserAdmin.php index 7e178320774..17b3cd69fab 100644 --- a/core/modules/user/src/Plugin/LanguageNegotiation/LanguageNegotiationUserAdmin.php +++ b/core/modules/user/src/Plugin/LanguageNegotiation/LanguageNegotiationUserAdmin.php @@ -10,6 +10,8 @@ namespace Drupal\user\Plugin\LanguageNegotiation; use Drupal\Core\PathProcessor\PathProcessorManager; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Routing\AdminContext; +use Drupal\Core\Routing\RouteMatch; +use Drupal\Core\Routing\StackedRouteMatchInterface; use Drupal\language\LanguageNegotiationMethodBase; use Symfony\Cmf\Component\Routing\RouteObjectInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -60,6 +62,13 @@ class LanguageNegotiationUserAdmin extends LanguageNegotiationMethodBase impleme */ protected $pathProcessorManager; + /** + * The stacked route match. + * + * @var \Drupal\Core\Routing\StackedRouteMatchInterface + */ + protected $stackedRouteMatch; + /** * Constructs a new LanguageNegotiationUserAdmin instance. * @@ -69,11 +78,14 @@ class LanguageNegotiationUserAdmin extends LanguageNegotiationMethodBase impleme * The router. * @param \Drupal\Core\PathProcessor\PathProcessorManager $path_processor_manager * The path processor manager. + * @param \Drupal\Core\Routing\StackedRouteMatchInterface $stacked_route_match + * The stacked route match. */ - public function __construct(AdminContext $admin_context, UrlMatcherInterface $router, PathProcessorManager $path_processor_manager) { + public function __construct(AdminContext $admin_context, UrlMatcherInterface $router, PathProcessorManager $path_processor_manager, StackedRouteMatchInterface $stacked_route_match) { $this->adminContext = $admin_context; $this->router = $router; $this->pathProcessorManager = $path_processor_manager; + $this->stackedRouteMatch = $stacked_route_match; } /** @@ -83,7 +95,8 @@ class LanguageNegotiationUserAdmin extends LanguageNegotiationMethodBase impleme return new static( $container->get('router.admin_context'), $container->get('router'), - $container->get('path_processor_manager') + $container->get('path_processor_manager'), + $container->get('current_route_match') ); } @@ -117,7 +130,8 @@ class LanguageNegotiationUserAdmin extends LanguageNegotiationMethodBase impleme // If called from an event subscriber, the request may not have the route // object yet (it is still being built), so use the router to look up // based on the path. - if (!$route_object = $request->attributes->get(RouteObjectInterface::ROUTE_OBJECT)) { + $route_match = $this->stackedRouteMatch->getRouteMatchFromRequest($request); + if ($route_match && !$route_object = $route_match->getRouteObject()) { try { // Process the path as an inbound path. This will remove any language // prefixes and other path components that inbound processing would diff --git a/core/modules/user/src/Plugin/views/argument_default/User.php b/core/modules/user/src/Plugin/views/argument_default/User.php index 850ee2ff77f..77fa69f8384 100644 --- a/core/modules/user/src/Plugin/views/argument_default/User.php +++ b/core/modules/user/src/Plugin/views/argument_default/User.php @@ -8,6 +8,7 @@ namespace Drupal\user\Plugin\views\argument_default; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Routing\RouteMatchInterface; use Drupal\views\Plugin\CacheablePluginInterface; use Drupal\views\Plugin\views\argument_default\ArgumentDefaultPluginBase; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -25,6 +26,44 @@ use Drupal\node\NodeInterface; */ class User extends ArgumentDefaultPluginBase implements CacheablePluginInterface { + /** + * The route match. + * + * @var \Drupal\Core\Routing\RouteMatchInterface + */ + protected $routeMatch; + + /** + * Constructs a new Date instance. + * + * @param array $configuration + * A configuration array containing information about the plugin instance. + * @param string $plugin_id + * The plugin_id for the plugin instance. + * @param mixed $plugin_definition + * The plugin implementation definition. + * + * @param \Drupal\Core\Routing\RouteMatchInterface $route_match + * The route match. + */ + public function __construct(array $configuration, $plugin_id, $plugin_definition, RouteMatchInterface $route_match) { + parent::__construct($configuration, $plugin_id, $plugin_definition); + + $this->routeMatch = $route_match; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('current_route_match') + ); + } + /** * {@inheritdoc} */ @@ -52,16 +91,14 @@ class User extends ArgumentDefaultPluginBase implements CacheablePluginInterface public function getArgument() { // If there is a user object in the current route. - if ($this->view->getRequest()->attributes->has('user')) { - $user = $this->view->getRequest()->attributes->get('user'); + if ($user = $this->routeMatch->getParameter('user')) { if ($user instanceof UserInterface) { return $user->id(); } } // If option to use node author; and node in current route. - if (!empty($this->options['user']) && $this->view->getRequest()->attributes->has('node')) { - $node = $this->view->getRequest()->attributes->get('node'); + if (!empty($this->options['user']) && $node = $this->routeMatch->getParameter('node')) { if ($node instanceof NodeInterface) { return $node->getOwnerId(); } diff --git a/core/modules/views/src/Plugin/views/argument/Date.php b/core/modules/views/src/Plugin/views/argument/Date.php index 3a3db7f01e3..457a0dff957 100644 --- a/core/modules/views/src/Plugin/views/argument/Date.php +++ b/core/modules/views/src/Plugin/views/argument/Date.php @@ -9,6 +9,8 @@ namespace Drupal\views\Plugin\views\argument; use Drupal\Core\Database\Database; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Plugin\ContainerFactoryPluginInterface; +use Drupal\Core\Routing\RouteMatchInterface; use Drupal\node\NodeInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Request; @@ -29,7 +31,7 @@ use Symfony\Component\HttpFoundation\Request; * * @ViewsArgument("date") */ -class Date extends Formula { +class Date extends Formula implements ContainerFactoryPluginInterface { /** * The date format used in the title. @@ -47,6 +49,44 @@ class Date extends Formula { var $option_name = 'default_argument_date'; + /** + * The route match. + * + * @var \Drupal\Core\Routing\RouteMatchInterface + */ + protected $routeMatch; + + /** + * Constructs a new Date instance. + * + * @param array $configuration + * A configuration array containing information about the plugin instance. + * @param string $plugin_id + * The plugin_id for the plugin instance. + * @param mixed $plugin_definition + * The plugin implementation definition. + * + * @param \Drupal\Core\Routing\RouteMatchInterface $route_match + * The route match. + */ + public function __construct(array $configuration, $plugin_id, $plugin_definition, RouteMatchInterface $route_match) { + parent::__construct($configuration, $plugin_id, $plugin_definition); + + $this->routeMatch = $route_match; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('current_route_match') + ); + } + /** * Add an option to set the default value to the current date. */ @@ -66,7 +106,7 @@ class Date extends Formula { return date($this->argFormat, REQUEST_TIME); } elseif (!$raw && in_array($this->options['default_argument_type'], array('node_created', 'node_changed'))) { - $node = $this->view->getRequest()->attributes->get('node'); + $node = $this->routeMatch->getParameter('node'); if (!($node instanceof NodeInterface)) { return parent::getDefaultArgument(); diff --git a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php index a49740df347..ce4c25b0063 100644 --- a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php +++ b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php @@ -2582,7 +2582,7 @@ abstract class DisplayPluginBase extends PluginBase { */ public function viewExposedFormBlocks() { // Avoid interfering with the admin forms. - $route_name = \Drupal::request()->attributes->get(RouteObjectInterface::ROUTE_NAME); + $route_name = \Drupal::routeMatch()->getRouteName(); if (strpos($route_name, 'views_ui.') === 0) { return; } diff --git a/core/tests/Drupal/Tests/Core/Controller/ControllerResolverTest.php b/core/tests/Drupal/Tests/Core/Controller/ControllerResolverTest.php index 91491c8cccb..d015a31c06f 100644 --- a/core/tests/Drupal/Tests/Core/Controller/ControllerResolverTest.php +++ b/core/tests/Drupal/Tests/Core/Controller/ControllerResolverTest.php @@ -74,8 +74,8 @@ class ControllerResolverTest extends UnitTestCase { )); $arguments = $this->controllerResolver->getArguments($request, $controller); - $this->assertEquals($mock_entity, $arguments[0], 'Type hinted variables should use upcasted values.'); - $this->assertEquals(1, $arguments[1], 'Not type hinted variables should use not upcasted values.'); + $this->assertEquals($mock_entity, $arguments[0]); + $this->assertEquals($mock_account, $arguments[1]); $this->assertEquals(RouteMatch::createFromRequest($request), $arguments[2], 'Ensure that the route match object is passed along as well'); } diff --git a/core/tests/Drupal/Tests/Core/Routing/CurrentRouteMatchTest.php b/core/tests/Drupal/Tests/Core/Routing/CurrentRouteMatchTest.php index 3293b84cc17..1d2942d48e5 100644 --- a/core/tests/Drupal/Tests/Core/Routing/CurrentRouteMatchTest.php +++ b/core/tests/Drupal/Tests/Core/Routing/CurrentRouteMatchTest.php @@ -78,4 +78,38 @@ class CurrentRouteMatchTest extends RouteMatchBaseTest { $this->assertSame('1', $current_route_match->getParameter('foo')); } + /** + * @covers ::getRouteMatchFromRequest + */ + public function testGetRouteMatchFromRequestWithRouting() { + $request_stack = new RequestStack(); + $request = new Request(); + $request_stack->push($request); + $current_route_match = new CurrentRouteMatch($request_stack); + + $route_match = $current_route_match->getRouteMatchFromRequest($request); + + $this->assertNull($route_match->getRouteName()); + $this->assertNull($route_match->getRouteObject()); + } + + /** + * @covers ::getRouteMatchFromRequest + */ + public function testGetRouteMatchFromRequest() { + $request_stack = new RequestStack(); + $request = new Request(); + $request_stack->push($request); + $route = new Route('/test-route/{foo}'); + + $request->attributes->set(RouteObjectInterface::ROUTE_NAME, 'test_route'); + $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, $route); + $request->attributes->set('foo', '1'); + $current_route_match = new CurrentRouteMatch($request_stack); + + $route_match = $current_route_match->getRouteMatchFromRequest($request); + $this->assertEquals('test_route', $route_match->getRouteName()); + $this->assertEquals($route, $route_match->getRouteObject()); + } + }