diff --git a/core/lib/Drupal/Core/Entity/EntityBase.php b/core/lib/Drupal/Core/Entity/EntityBase.php index a42ef48336..463e0003c0 100644 --- a/core/lib/Drupal/Core/Entity/EntityBase.php +++ b/core/lib/Drupal/Core/Entity/EntityBase.php @@ -275,6 +275,8 @@ protected function urlRouteParameters($rel) { $uri_route_parameters[$this->getEntityTypeId() . '_revision'] = $this->getRevisionId(); } + \Drupal::moduleHandler()->alter([$this->entityTypeId . '_url_route_parameters', 'entity_url_route_parameters'], $uri_route_parameters, $this, $rel); + return $uri_route_parameters; } diff --git a/core/lib/Drupal/Core/Entity/entity.api.php b/core/lib/Drupal/Core/Entity/entity.api.php index 38a77553d6..eb755ce63c 100644 --- a/core/lib/Drupal/Core/Entity/entity.api.php +++ b/core/lib/Drupal/Core/Entity/entity.api.php @@ -2276,6 +2276,24 @@ function hook_entity_extra_field_info_alter(&$info) { } } +/** + * + * @param string[] $parameters + * The URL route parameters. + * @param \Drupal\Core\Entity\EntityInterface $entity + * The entity for which the URL route parameters are used. + * @param string $rel + * The link relationship type, for example: canonical or edit-form. + * + * @see \Drupal\Core\Entity\Entity::urlRouteParameters() + * @see hook_entity_url_route_parameters_alter() + */ +function hook_ENTITY_TYPE_url_route_parameters_alter(&$parameters, \Drupal\Core\Entity\EntityInterface $entity, $rel) { + if ($rel == 'canonical') { + $parameters['uuid'] = $entity->uuid(); + } +} + /** * @} End of "addtogroup hooks". */ diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityLinkTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityLinkTest.php index 978ab70e3a..43b0f3546b 100644 --- a/core/tests/Drupal/Tests/Core/Entity/EntityLinkTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/EntityLinkTest.php @@ -7,6 +7,7 @@ use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Language\Language; use Drupal\Core\Link; +use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Tests\UnitTestCase; /** @@ -36,6 +37,13 @@ class EntityLinkTest extends UnitTestCase { */ protected $languageManager; + /** + * Module handler mock. + * + * @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $moduleHandler; + /** * {@inheritdoc} */ @@ -45,11 +53,13 @@ protected function setUp(): void { $this->entityTypeManager = $this->createMock(EntityTypeManagerInterface::class); $this->linkGenerator = $this->createMock('Drupal\Core\Utility\LinkGeneratorInterface'); $this->languageManager = $this->createMock('Drupal\Core\Language\LanguageManagerInterface'); + $this->moduleHandler = $this->createMock(ModuleHandlerInterface::class); $container = new ContainerBuilder(); $container->set('entity_type.manager', $this->entityTypeManager); $container->set('link_generator', $this->linkGenerator); $container->set('language_manager', $this->languageManager); + $container->set('module_handler', $this->moduleHandler); \Drupal::setContainer($container); } diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityUrlTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityUrlTest.php index 9af542afa2..db8a9b4505 100644 --- a/core/tests/Drupal/Tests/Core/Entity/EntityUrlTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/EntityUrlTest.php @@ -14,6 +14,7 @@ use Drupal\Core\Url; use Drupal\Tests\UnitTestCase; use Symfony\Component\Routing\Exception\MissingMandatoryParametersException; +use Drupal\Core\Extension\ModuleHandlerInterface; /** * Tests URL handling of the \Drupal\Core\Entity\EntityBase class. @@ -66,6 +67,20 @@ class EntityUrlTest extends UnitTestCase { */ protected $langcode = 'en'; + /** + * Module handler mock. + * + * @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $moduleHandler; + + /** + * The URL generator. + * + * @var \Drupal\Core\Routing\UrlGeneratorInterface + */ + protected $urlGenerator; + /** * Indicator for default revisions. * @@ -94,6 +109,21 @@ class EntityUrlTest extends UnitTestCase { */ const HAS_BUNDLE_KEY = TRUE; + /** + * {@inheritdoc} + */ + protected function setUp(): void { + parent::setUp(); + + $this->moduleHandler = $this->createMock(ModuleHandlerInterface::class); + $this->urlGenerator = $this->createMock(UrlGeneratorInterface::class); + + $container = new ContainerBuilder(); + $container->set('url_generator', $this->urlGenerator); + $container->set('module_handler', $this->moduleHandler); + \Drupal::setContainer($container); + } + /** * Tests the toUrl() method without an entity ID. * @@ -107,6 +137,26 @@ public function testToUrlNoId() { $entity->toUrl(); } + /** + * Tests the urlRouteParameter() alter hook. + * + * @covers ::toUrl + * @covers ::urlRouteParameters + */ + public function testUrlRouteParameterAlterHook() { + $values = ['id' => $this->entityId, 'langcode' => $this->langcode]; + $entity = $this->getEntity(Entity::class, $values); + $this->registerLinkTemplate('canonical'); + + $this->moduleHandler->expects($this->atLeastOnce()) + ->method('alter') + ->willReturnCallback(function ($hook, &$parameters, $entity, $rel) { + $parameters['new_param'] = 'altered'; + }); + + $this->assertArrayHasKey('new_param', $entity->toUrl()->getRouteParameters()); + } + /** * Tests the toUrl() method with simple link templates. * @@ -387,15 +437,10 @@ public function providerTestToUrlUriCallback() { public function testUriRelationships() { $entity = $this->getEntity(UrlTestEntity::class, ['id' => $this->entityId]); - $container_builder = new ContainerBuilder(); - $url_generator = $this->createMock(UrlGeneratorInterface::class); - $container_builder->set('url_generator', $url_generator); - \Drupal::setContainer($container_builder); - // Test route with no mandatory parameters. $this->registerLinkTemplate('canonical'); $route_name_0 = 'entity.' . $this->entityTypeId . '.canonical'; - $url_generator->expects($this->any()) + $this->urlGenerator->expects($this->any()) ->method('generateFromRoute') ->with($route_name_0) ->willReturn((new GeneratedUrl())->setGeneratedUrl('/entity_test')); @@ -404,7 +449,7 @@ public function testUriRelationships() { // Test route with non-default mandatory parameters. $this->registerLinkTemplate('{non_default_parameter}'); $route_name_1 = 'entity.' . $this->entityTypeId . '.{non_default_parameter}'; - $url_generator->expects($this->any()) + $this->urlGenerator->expects($this->any()) ->method('generateFromRoute') ->with($route_name_1) ->willThrowException(new MissingMandatoryParametersException($route_name_1, ['missing_parameter']));