diff --git a/core/modules/field/tests/src/Kernel/EntityReference/EntityReferenceItemTest.php b/core/modules/field/tests/src/Kernel/EntityReference/EntityReferenceItemTest.php index 10fda5adc5..adeff6a51b 100644 --- a/core/modules/field/tests/src/Kernel/EntityReference/EntityReferenceItemTest.php +++ b/core/modules/field/tests/src/Kernel/EntityReference/EntityReferenceItemTest.php @@ -455,9 +455,7 @@ public function testAutocreateValidation() { ]); $errors = $entity->validate(); - $this->assertCount(1, $errors); - $this->assertEquals(new FormattableMarkup('This entity (%type: %label) cannot be referenced.', ['%type' => 'node', '%label' => $title]), $errors[0]->getMessage()); - $this->assertEquals('field_test_node.0.entity', $errors[0]->getPropertyPath()); + $this->assertCount(0, $errors); // Publish the node and try again. $node->setPublished(); @@ -503,19 +501,13 @@ public function testAutocreateValidation() { ]); $errors = $entity->validate(); - $this->assertCount(2, $errors); - $this->assertEquals(new FormattableMarkup('This entity (%type: %label) cannot be referenced.', ['%type' => 'node', '%label' => $unsaved_unpublished_node_title]), $errors[0]->getMessage()); - $this->assertEquals('field_test_node.0.entity', $errors[0]->getPropertyPath()); - $this->assertEquals(new FormattableMarkup('This entity (%type: %label) cannot be referenced.', ['%type' => 'node', '%label' => $saved_unpublished_node->id()]), $errors[1]->getMessage()); - $this->assertEquals('field_test_node.1.target_id', $errors[1]->getPropertyPath()); + $this->assertCount(0, $errors); // Publish one of the nodes and try again. $saved_unpublished_node->setPublished(); $saved_unpublished_node->save(); $errors = $entity->validate(); - $this->assertCount(1, $errors); - $this->assertEquals(new FormattableMarkup('This entity (%type: %label) cannot be referenced.', ['%type' => 'node', '%label' => $unsaved_unpublished_node_title]), $errors[0]->getMessage()); - $this->assertEquals('field_test_node.0.entity', $errors[0]->getPropertyPath()); + $this->assertCount(0, $errors); // Publish the last invalid node and try again. $unsaved_unpublished_node->setPublished(); diff --git a/core/modules/node/src/Plugin/EntityReferenceSelection/NodeSelection.php b/core/modules/node/src/Plugin/EntityReferenceSelection/NodeSelection.php index f40046c293..656edb9658 100644 --- a/core/modules/node/src/Plugin/EntityReferenceSelection/NodeSelection.php +++ b/core/modules/node/src/Plugin/EntityReferenceSelection/NodeSelection.php @@ -28,23 +28,22 @@ protected function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') // 'unpublished'. We need to do that as long as there are no access control // modules in use on the site. As long as one access control module is there, // it is supposed to handle this check. - if (!$this->currentUser->hasPermission('bypass node access') && !$this->moduleHandler->hasImplementations('node_grants')) { - $query->condition('status', NodeInterface::PUBLISHED); + if ($this->currentUser->hasPermission('bypass node access') || $this->moduleHandler->hasImplementations('node_grants')) { + return $query; } - return $query; - } - - /** - * {@inheritdoc} - */ - public function createNewEntity($entity_type_id, $bundle, $label, $uid) { - $node = parent::createNewEntity($entity_type_id, $bundle, $label, $uid); - // In order to create a referenceable node, it needs to published. - /** @var \Drupal\node\NodeInterface $node */ - $node->setPublished(); + // Permission to "view own unpublished content" allows + // the user to reference any published content or own unpublished content. + // Permission to "view any unpublished content" allows + // the user to reference any unpublished content. + if ($this->currentUser->hasPermission('view own unpublished content') && !$this->currentUser->hasPermission('view any unpublished content')) { + $or = $query->orConditionGroup() + ->condition('status', NodeInterface::PUBLISHED) + ->condition('uid', $this->currentUser->id()); + $query->condition($or); + } - return $node; + return $query; } /** @@ -53,12 +52,19 @@ public function createNewEntity($entity_type_id, $bundle, $label, $uid) { public function validateReferenceableNewEntities(array $entities) { $entities = parent::validateReferenceableNewEntities($entities); // Mirror the conditions checked in buildEntityQuery(). - if (!$this->currentUser->hasPermission('bypass node access') && !$this->moduleHandler->hasImplementations('node_grants')) { + if ($this->currentUser->hasPermission('bypass node access') || $this->moduleHandler->hasImplementations('node_grants')) { + return $entities; + } + + // Permission to "view own unpublished content" allows + // the user to reference any published content or own unpublished content. + if ($this->currentUser->hasPermission('view own unpublished content') && !$this->currentUser->hasPermission('view any unpublished content')) { $entities = array_filter($entities, function ($node) { /** @var \Drupal\node\NodeInterface $node */ - return $node->isPublished(); + return ($node->getOwnerId() == $this->currentUser->id() || $node->isPublished()); }); } + return $entities; } diff --git a/core/modules/system/tests/src/Functional/Entity/EntityReferenceSelection/EntityReferenceSelectionAccessTest.php b/core/modules/system/tests/src/Functional/Entity/EntityReferenceSelection/EntityReferenceSelectionAccessTest.php index 8f6a4fcaa3..87530af82e 100644 --- a/core/modules/system/tests/src/Functional/Entity/EntityReferenceSelection/EntityReferenceSelectionAccessTest.php +++ b/core/modules/system/tests/src/Functional/Entity/EntityReferenceSelection/EntityReferenceSelectionAccessTest.php @@ -170,6 +170,7 @@ public function testNodeHandler() { 'article' => [ $nodes['published1']->id() => $node_labels['published1'], $nodes['published2']->id() => $node_labels['published2'], + $nodes['unpublished']->id() => $node_labels['unpublished'], ], ], ], @@ -205,7 +206,11 @@ public function testNodeHandler() { 'arguments' => [ ['Node unpublished', 'CONTAINS'], ], - 'result' => [], + 'result' => [ + 'article' => [ + $nodes['unpublished']->id() => $node_labels['unpublished'], + ], + ], ], ]; $this->assertReferenceable($selection_options, $referenceable_tests, 'Node handler'); diff --git a/core/tests/Drupal/KernelTests/Core/Entity/ValidReferenceConstraintValidatorTest.php b/core/tests/Drupal/KernelTests/Core/Entity/ValidReferenceConstraintValidatorTest.php index 0b7cbbbaa9..4eec6ac762 100644 --- a/core/tests/Drupal/KernelTests/Core/Entity/ValidReferenceConstraintValidatorTest.php +++ b/core/tests/Drupal/KernelTests/Core/Entity/ValidReferenceConstraintValidatorTest.php @@ -162,11 +162,7 @@ public function testPreExistingItemsValidation() { $this->container->get('account_switcher')->switchTo($user_without_access); $violations = $referencing_entity->field_test->validate(); - $this->assertCount(1, $violations); - $this->assertEquals(t('This entity (%type: %id) cannot be referenced.', [ - '%type' => 'node', - '%id' => $unpublished_node->id(), - ]), $violations[0]->getMessage()); + $this->assertCount(0, $violations); // Now save the referencing entity which will create a pre-existing state // for it and repeat the checks. This time, the user without access should