diff --git a/core/core.services.yml b/core/core.services.yml index e791572..e74e688 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -1162,6 +1162,10 @@ services: arguments: ['@current_route_match'] tags: - { name: route_processor_outbound, priority: 200 } + route_processor_entity_uuid: + class: Drupal\Core\RouteProcessor\RouteProcessorEntityUUID + tags: + - { name: route_processor_outbound, priority: } path_processor_alias: class: Drupal\Core\PathProcessor\PathProcessorAlias tags: diff --git a/core/lib/Drupal/Core/Menu/DefaultMenuLinkTreeManipulators.php b/core/lib/Drupal/Core/Menu/DefaultMenuLinkTreeManipulators.php index 9461683..381baf3 100644 --- a/core/lib/Drupal/Core/Menu/DefaultMenuLinkTreeManipulators.php +++ b/core/lib/Drupal/Core/Menu/DefaultMenuLinkTreeManipulators.php @@ -140,7 +140,9 @@ public function checkNodeAccess(array $tree) { $nids = array_keys($node_links); $query = $this->queryFactory->get('node'); - $query->condition('nid', $nids, 'IN'); + $query->orConditionGroup() + ->condition('nid', $nids, 'IN') + ->condition('uuid', $nids, 'IN'); // Allows admins to view all nodes, by both disabling node_access // query rewrite as well as not checking for the node status. The diff --git a/core/lib/Drupal/Core/ParamConverter/EntityConverter.php b/core/lib/Drupal/Core/ParamConverter/EntityConverter.php index 172b27b..780b61c 100644 --- a/core/lib/Drupal/Core/ParamConverter/EntityConverter.php +++ b/core/lib/Drupal/Core/ParamConverter/EntityConverter.php @@ -7,6 +7,7 @@ namespace Drupal\Core\ParamConverter; +use Drupal\Component\Uuid\Uuid; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\TypedData\TranslatableInterface; @@ -67,6 +68,12 @@ public function convert($value, $definition, $name, array $defaults) { $entity_type_id = $this->getEntityTypeFromDefaults($definition, $name, $defaults); if ($storage = $this->entityManager->getStorage($entity_type_id)) { $entity = $storage->load($value); + // If there is no entity loadable by ID, try to load by UUID. + if (!$entity && Uuid::isValid($value)) { + if ($entities = $storage->loadByProperties(['uuid' => $value])) { + $entity = reset($entities); + } + } // If the entity type is translatable, ensure we return the proper // translation object for the current context. if ($entity instanceof EntityInterface && $entity instanceof TranslatableInterface) { diff --git a/core/lib/Drupal/Core/RouteProcessor/RouteProcessorEntityUUID.php b/core/lib/Drupal/Core/RouteProcessor/RouteProcessorEntityUUID.php new file mode 100644 index 0000000..2fe8bf1 --- /dev/null +++ b/core/lib/Drupal/Core/RouteProcessor/RouteProcessorEntityUUID.php @@ -0,0 +1,50 @@ +entityManager = $entity_manager; + } + + /** + * {@inheritdoc} + */ + public function processOutbound($route_name, Route $route, array &$parameters) { + if (strpos($route_name, 'entity.') === 0 && list(, $entity_type, $operation) = explode('.', $route_name)) { + if (isset($parameters[$entity_type]) && strlen($parameters[$entity_type]) === 32) { + if ($entities = $this->entityManager->getStorage($entity_type)->loadByProperties(['uuid' => $parameters[$entity_type]])) { + /** @var \Drupal\Core\Entity\EntityInterface $entity */ + $entity = reset($entities); + $parameters[$entity_type] = $entity->id(); + } + } + } + } + +} diff --git a/core/tests/Drupal/Tests/Core/ParamConverter/EntityConverterTest.php b/core/tests/Drupal/Tests/Core/ParamConverter/EntityConverterTest.php index 36919a6..04075a8 100644 --- a/core/tests/Drupal/Tests/Core/ParamConverter/EntityConverterTest.php +++ b/core/tests/Drupal/Tests/Core/ParamConverter/EntityConverterTest.php @@ -93,6 +93,12 @@ public function testConvert($value, array $definition, array $defaults, $expecte ['valid_id', (object) ['id' => 'valid_id']], ['invalid_id', NULL], ]); + $entity_storage->expects($this->any()) + ->method('loadByProperties') + ->willReturnMap([ + [['uuid' => 'invalid_id'], NULL], + [['uuid' => $value], [(object) ['uuid' => $value, 'id' => 'valid_id']]], + ]); $this->assertEquals($expected_result, $this->entityConverter->convert($value, $definition, 'foo', $defaults)); } @@ -106,8 +112,10 @@ public function providerTestConvert() { $data[] = ['valid_id', ['type' => 'entity:entity_test'], ['foo' => 'valid_id'], (object) ['id' => 'valid_id']]; // Invalid ID. $data[] = ['invalid_id', ['type' => 'entity:entity_test'], ['foo' => 'invalid_id'], NULL]; - // Entity type placeholder. +// Entity type placeholder. $data[] = ['valid_id', ['type' => 'entity:{entity_type}'], ['foo' => 'valid_id', 'entity_type' => 'entity_test'], (object) ['id' => 'valid_id']]; + // UUID. + $data[] = ['1c5217f4-553c-40d8-8389-a3cc3529d79c', ['type' => 'entity:entity_test'], ['foo' => '1c5217f4-553c-40d8-8389-a3cc3529d79c'], (object) ['uuid' => '1c5217f4-553c-40d8-8389-a3cc3529d79c', 'id' => 'valid_id']]; return $data; }