diff --git a/core/lib/Drupal/Core/Url.php b/core/lib/Drupal/Core/Url.php index a37627e..6360965 100644 --- a/core/lib/Drupal/Core/Url.php +++ b/core/lib/Drupal/Core/Url.php @@ -326,7 +326,7 @@ public static function fromUri($uri, $options = []) { * * @param array $uri_parts * Parts from an URI of the form entity:{entity_type}/{entity_id} as from - * parse_url(). Note that {entity_id} can be both a UUID and a serial ID. + * parse_url(). Note that {entity_id} can be either a UUID or the entity ID. * @param array $options * An array of options, see \Drupal\Core\Url::fromUri() for details. * @param string $uri diff --git a/core/modules/menu_ui/src/Tests/MenuNodeTest.php b/core/modules/menu_ui/src/Tests/MenuNodeTest.php index a6d7f18..07a8a43 100644 --- a/core/modules/menu_ui/src/Tests/MenuNodeTest.php +++ b/core/modules/menu_ui/src/Tests/MenuNodeTest.php @@ -349,6 +349,7 @@ public function testNodeUuidLink() { $menu_name = 'main'; $type->setThirdPartySetting('menu_ui', 'available_menus', [$menu_name]); $type->save(); + // Test links using node/{uuid}. $node6 = $this->drupalCreateNode(array('type' => 'page')); $uuid_link = $this->addMenuLink('', '/node/' . $node6->uuid(), $menu_name); @@ -360,6 +361,7 @@ public function testNodeUuidLink() { /** @var \Drupal\menu_link_content\MenuLinkContentInterface $uuid_link */ $uuid_link = MenuLinkContent::load($uuid_link->id()); $this->assertEqual($uuid_link->getUrlObject(), Url::fromUri('internal:/node/' . $node6->uuid())); + // Test with entity:node/{uuid}. $node7 = $this->drupalCreateNode(array('type' => 'page')); $uuid_link = $this->addMenuLink('', 'entity:node/' . $node7->uuid(), $menu_name); diff --git a/core/modules/views/src/Plugin/views/argument_validator/Entity.php b/core/modules/views/src/Plugin/views/argument_validator/Entity.php index 53e29d7..5972777 100644 --- a/core/modules/views/src/Plugin/views/argument_validator/Entity.php +++ b/core/modules/views/src/Plugin/views/argument_validator/Entity.php @@ -2,6 +2,7 @@ namespace Drupal\views\Plugin\views\argument_validator; +use Drupal\Component\Uuid\Uuid; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Form\FormStateInterface; @@ -168,8 +169,28 @@ public function validateArgument($argument) { else { return FALSE; } + $uuids = array_filter($ids, function ($value) { + return Uuid::isValid($value); + }); + $ids = array_diff($ids, $uuids); + + $storage = $this->entityManager->getStorage($entity_type); + if ($uuids) { + foreach ($uuids as $uuid) { + if ($entities = $storage->loadByProperties(['uuid' => $uuid])) { + $entity = reset($entities); + if (!$this->validateEntity($entity)) { + return FALSE; + } + } + else { + // Missing UUID, break and return false. + return FALSE; + } + } + } + $entities = $storage->loadMultiple($ids); - $entities = $this->entityManager->getStorage($entity_type)->loadMultiple($ids); // Validate each id => entity. If any fails break out and return false. foreach ($ids as $id) { // There is no entity for this ID. diff --git a/core/modules/views/tests/src/Unit/Plugin/argument_validator/EntityTest.php b/core/modules/views/tests/src/Unit/Plugin/argument_validator/EntityTest.php index f9ca7d8..0d75fab 100644 --- a/core/modules/views/tests/src/Unit/Plugin/argument_validator/EntityTest.php +++ b/core/modules/views/tests/src/Unit/Plugin/argument_validator/EntityTest.php @@ -88,6 +88,13 @@ protected function setUp() { ->method('loadMultiple') ->will($this->returnValueMap($value_map)); + $uuid_value_map = [ + [['uuid' => 'fb0920d9-7a0d-42c5-8d11-b31d9ebfae6b'], [1 => $mock_entity]], + ]; + $storage->expects($this->any()) + ->method('loadByProperties') + ->will($this->returnValueMap($uuid_value_map)); + $this->entityManager->expects($this->any()) ->method('getStorage') ->with('entity_test') @@ -122,7 +129,9 @@ public function testValidateArgumentNoAccess() { $this->assertFalse($this->argumentValidator->validateArgument('')); $this->assertTrue($this->argumentValidator->validateArgument(1)); - $this->assertTrue($this->argumentValidator->validateArgument(2)); + $this->assertTrue($this->argumentValidator->validateArgument(1)); + $this->assertTrue($this->argumentValidator->validateArgument('fb0920d9-7a0d-42c5-8d11-b31d9ebfae6b')); + $this->assertFalse($this->argumentValidator->validateArgument('298109c5-c931-4367-af2b-356008905ed1')); $this->assertFalse($this->argumentValidator->validateArgument('1,2')); } diff --git a/core/tests/Drupal/Tests/Core/Menu/DefaultMenuLinkTreeManipulatorsTest.php b/core/tests/Drupal/Tests/Core/Menu/DefaultMenuLinkTreeManipulatorsTest.php index ba09ac9..156d490 100644 --- a/core/tests/Drupal/Tests/Core/Menu/DefaultMenuLinkTreeManipulatorsTest.php +++ b/core/tests/Drupal/Tests/Core/Menu/DefaultMenuLinkTreeManipulatorsTest.php @@ -275,19 +275,21 @@ public function testCheckNodeAccessUuidAndNid() { 1 => MenuLinkMock::create(array('id' => 'node.1', 'route_name' => 'entity.node.canonical', 'title' => 'foo', 'parent' => '', 'route_parameters' => array('node' => 1))), 2 => MenuLinkMock::create(array('id' => 'node.2', 'route_name' => 'entity.node.canonical', 'title' => 'bar', 'parent' => '', 'route_parameters' => array('node' => 2))), 3 => MenuLinkMock::create(array('id' => 'node.3', 'route_name' => 'entity.node.canonical', 'title' => 'baz', 'parent' => 'node.2', 'route_parameters' => array('node' => 3))), - 4 => MenuLinkMock::create(array('id' => 'node.4', 'route_name' => 'entity.node.uuid', 'title' => 'qux', 'parent' => 'node.3', 'route_parameters' => array('node' => '7910d537-04be-450a-8200-b53f49ea6b30'))), - 5 => MenuLinkMock::create(array('id' => 'test.1', 'route_name' => 'test_route', 'title' => 'qux', 'parent' => '')), - 6 => MenuLinkMock::create(array('id' => 'test.2', 'route_name' => 'test_route', 'title' => 'qux', 'parent' => 'test.1')), + 4 => MenuLinkMock::create(array('id' => 'node.4', 'route_name' => 'entity.node.uuid', 'title' => 'qux', 'parent' => 'node.3', 'route_parameters' => array('node' => 4))), + 5 => MenuLinkMock::create(array('id' => 'node.5', 'route_name' => 'entity.node.uuid', 'title' => 'qux', 'parent' => 'node.3', 'route_parameters' => array('node' => '7910d537-04be-450a-8200-b53f49ea6b30'))), + 6 => MenuLinkMock::create(array('id' => 'test.1', 'route_name' => 'test_route', 'title' => 'qux', 'parent' => '')), + 7 => MenuLinkMock::create(array('id' => 'test.2', 'route_name' => 'test_route', 'title' => 'qux', 'parent' => 'test.1')), ); $tree = array(); $tree[1] = new MenuLinkTreeElement($links[1], FALSE, 1, FALSE, array()); $tree[2] = new MenuLinkTreeElement($links[2], TRUE, 1, FALSE, array( 3 => new MenuLinkTreeElement($links[3], TRUE, 2, FALSE, array( 4 => new MenuLinkTreeElement($links[4], FALSE, 3, FALSE, array()), + 5 => new MenuLinkTreeElement($links[5], FALSE, 3, FALSE, array()), )), )); - $tree[5] = new MenuLinkTreeElement($links[5], TRUE, 1, FALSE, array( - 6 => new MenuLinkTreeElement($links[6], FALSE, 2, FALSE, array()), + $tree[6] = new MenuLinkTreeElement($links[6], TRUE, 1, FALSE, array( + 7 => new MenuLinkTreeElement($links[7], FALSE, 2, FALSE, array()), )); $query = $this->getMock(QueryAggregateInterface::class); @@ -305,11 +307,11 @@ public function testCheckNodeAccessUuidAndNid() { ->willReturn($condition); $condition->expects($this->at(0)) ->method('condition') - ->with('nid', [1, 2, 3]) + ->with('nid', [1, 2, 3, 4]) ->willReturn($condition); $condition->expects($this->at(1)) ->method('condition') - ->with('uuid', [3 => '7910d537-04be-450a-8200-b53f49ea6b30']) + ->with('uuid', [4 => '7910d537-04be-450a-8200-b53f49ea6b30']) ->willReturn($condition); $query->expects($this->at(3)) ->method('condition') @@ -338,8 +340,8 @@ public function testCheckNodeAccessUuidAndNid() { $this->assertEquals(AccessResult::neutral(), $tree[2]->subtree[3]->access); $this->assertEquals($node_access_result, $tree[2]->subtree[3]->subtree[4]->access); // Ensure that other routes than entity.node.canonical are set as well. - $this->assertNull($tree[5]->access); - $this->assertNull($tree[5]->subtree[6]->access); + $this->assertNull($tree[6]->access); + $this->assertNull($tree[6]->subtree[7]->access); // On top of the node access checking now run the ordinary route based // access checkers. @@ -358,8 +360,8 @@ public function testCheckNodeAccessUuidAndNid() { $this->assertEquals($node_access_result, $tree[1]->access); $this->assertEquals($node_access_result, $tree[2]->access); $this->assertEquals(AccessResult::neutral(), $tree[2]->subtree[3]->access); - $this->assertEquals(AccessResult::allowed()->cachePerPermissions(), $tree[5]->access); - $this->assertEquals(AccessResult::neutral()->cachePerPermissions(), $tree[5]->subtree[6]->access); + $this->assertEquals(AccessResult::allowed()->cachePerPermissions(), $tree[6]->access); + $this->assertEquals(AccessResult::neutral()->cachePerPermissions(), $tree[6]->subtree[7]->access); } /**