diff --git a/core/modules/comment/src/CommentAccessControlHandler.php b/core/modules/comment/src/CommentAccessControlHandler.php index 516a2912329b4fbf61aca781f501283121e9c67f..ce12f12d5a48614fe7a0d0e04e1847c8e8835ae8 100644 --- a/core/modules/comment/src/CommentAccessControlHandler.php +++ b/core/modules/comment/src/CommentAccessControlHandler.php @@ -2,6 +2,7 @@ namespace Drupal\comment; +use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface; use Drupal\Core\Access\AccessResult; use Drupal\Core\Entity\EntityAccessControlHandler; use Drupal\Core\Entity\EntityInterface; @@ -98,9 +99,22 @@ protected function checkFieldAccess($operation, FieldDefinitionInterface $field_ 'field_name', 'pid', ]; - if ($items && ($entity = $items->getEntity()) && $entity->isNew() && in_array($field_definition->getName(), $create_only_fields, TRUE)) { - // We are creating a new comment, user can edit create only fields. - return AccessResult::allowedIfHasPermission($account, 'post comments')->addCacheableDependency($entity); + /** @var \Drupal\comment\CommentInterface|null $entity */ + $entity = $items ? $items->getEntity() : NULL; + $commented_entity = $entity ? $entity->getCommentedEntity() : NULL; + if ($entity && $entity->isNew() && in_array($field_definition->getName(), $create_only_fields, TRUE)) { + $access_result = AccessResult::allowedIfHasPermission($account, 'post comments') + ->addCacheableDependency($entity); + $comment_field_name = $entity->get('field_name')->value; + if ($commented_entity && $comment_field_name) { + // We are creating a new comment, user can edit create only fields if + // commenting is open. + $commenting_status = (int) $commented_entity->get($comment_field_name)->status; + $access_result = $access_result + ->andIf(AccessResult::allowedIf($commenting_status !== CommentItemInterface::CLOSED)) + ->addCacheableDependency($commented_entity); + } + return $access_result; } // We are editing an existing comment - create only fields are now read // only. @@ -121,9 +135,6 @@ protected function checkFieldAccess($operation, FieldDefinitionInterface $field_ return AccessResult::forbidden(); } $is_name = $field_definition->getName() === 'name'; - /** @var \Drupal\comment\CommentInterface $entity */ - $entity = $items->getEntity(); - $commented_entity = $entity->getCommentedEntity(); $anonymous_contact = $commented_entity->get($entity->getFieldName())->getFieldDefinition()->getSetting('anonymous'); $admin_access = AccessResult::allowedIfHasPermission($account, 'administer comments'); $anonymous_access = AccessResult::allowedIf($entity->isNew() && $account->isAnonymous() && ($anonymous_contact != CommentInterface::ANONYMOUS_MAYNOT_CONTACT || $is_name) && $account->hasPermission('post comments')) diff --git a/core/modules/comment/tests/src/Functional/Rest/CommentResourceTestBase.php b/core/modules/comment/tests/src/Functional/Rest/CommentResourceTestBase.php index 67c3bd12dd54ab844f8a1e875579ee5a77edbc04..8a61e2b9be09f4d95fbf7eaa1dc26a33e773ef99 100644 --- a/core/modules/comment/tests/src/Functional/Rest/CommentResourceTestBase.php +++ b/core/modules/comment/tests/src/Functional/Rest/CommentResourceTestBase.php @@ -4,6 +4,7 @@ use Drupal\comment\Entity\Comment; use Drupal\comment\Entity\CommentType; +use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface; use Drupal\comment\Tests\CommentTestTrait; use Drupal\Core\Cache\Cache; use Drupal\entity_test\Entity\EntityTest; @@ -94,6 +95,7 @@ protected function createEntity() { $commented_entity = EntityTest::create([ 'name' => 'Camelids', 'type' => 'bar', + 'comment' => CommentItemInterface::OPEN, ]); $commented_entity->save(); diff --git a/core/modules/comment/tests/src/Kernel/CommentFieldAccessTest.php b/core/modules/comment/tests/src/Kernel/CommentFieldAccessTest.php index 0fb3401efdb37cf63fabf1d482a15e683f7ab9a6..a284a49aa01c5ff8e8741af5b877e49cb6405053 100644 --- a/core/modules/comment/tests/src/Kernel/CommentFieldAccessTest.php +++ b/core/modules/comment/tests/src/Kernel/CommentFieldAccessTest.php @@ -5,6 +5,7 @@ use Drupal\comment\CommentInterface; use Drupal\comment\Entity\Comment; use Drupal\comment\Entity\CommentType; +use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface; use Drupal\comment\Tests\CommentTestTrait; use Drupal\Component\Render\FormattableMarkup; use Drupal\Core\Session\AnonymousUserSession; @@ -103,10 +104,6 @@ public function testAccessToAdministrativeFields() { ]); $comment_type->save(); - // Create a comment against a test entity. - $host = EntityTest::create(); - $host->save(); - // An administrator user. No user exists yet, ensure that the first user // does not have UID 1. $comment_admin_user = $this->createUser([ @@ -141,6 +138,15 @@ public function testAccessToAdministrativeFields() { $this->addDefaultCommentField('entity_test', 'entity_test', 'comment'); $this->addDefaultCommentField('entity_test', 'entity_test', 'comment_other'); + // Create a comment against a test entity. + $host = EntityTest::create(); + $host->save(); + + $host2 = EntityTest::create(); + $host2->comment->status = CommentItemInterface::CLOSED; + $host2->comment_other->status = CommentItemInterface::CLOSED; + $host2->save(); + // Change the second field's anonymous contact setting. $instance = FieldConfig::loadByName('entity_test', 'entity_test', 'comment_other'); // Default is 'May not contact', for this field - they may contact. @@ -200,10 +206,24 @@ public function testAccessToAdministrativeFields() { 'pid' => 0, 'uid' => $anonymous_user->id(), ]); + // Note we intentionally don't save this comment so it remains 'new'. + $comment5 = Comment::create([ + 'entity_type' => 'entity_test', + 'hostname' => 'magic.example.com', + // Unpublished. + 'status' => 0, + 'subject' => 'Wally the Border Collie', + // This one is closed for comments. + 'entity_id' => $host2->id(), + 'comment_type' => 'comment', + 'field_name' => 'comment_other', + 'pid' => 0, + 'uid' => $anonymous_user->id(), + ]); // Generate permutations. $combinations = [ - 'comment' => [$comment1, $comment2, $comment3, $comment4], + 'comment' => [$comment1, $comment2, $comment3, $comment4, $comment5], 'user' => [$comment_admin_user, $comment_enabled_user, $comment_no_edit_user, $comment_disabled_user, $anonymous_user], ]; $permutations = $this->generatePermutations($combinations); @@ -278,9 +298,10 @@ public function testAccessToAdministrativeFields() { '@comment' => $set['comment']->getSubject(), '@field' => $field, ])); - $this->assertEquals($may_update, $set['user']->hasPermission('post comments') && $set['comment']->isNew(), new FormattableMarkup('User @user @state update field @field on comment @comment', [ + $expected = $set['user']->hasPermission('post comments') && $set['comment']->isNew() && (int) $set['comment']->getCommentedEntity()->get($set['comment']->getFieldName())->status !== CommentItemInterface::CLOSED; + $this->assertEquals($expected, $may_update, new FormattableMarkup('User @user @state update field @field on comment @comment', [ '@user' => $set['user']->getAccountName(), - '@state' => $may_update ? 'can' : 'cannot', + '@state' => $expected ? 'can' : 'cannot', '@comment' => $set['comment']->getSubject(), '@field' => $field, ])); diff --git a/core/modules/jsonapi/tests/src/Functional/CommentTest.php b/core/modules/jsonapi/tests/src/Functional/CommentTest.php index 7600981eba4ec45743d56bd7675415690249da6e..ffc4db25356c0899ced2d6dbf77d4aca0d17072c 100644 --- a/core/modules/jsonapi/tests/src/Functional/CommentTest.php +++ b/core/modules/jsonapi/tests/src/Functional/CommentTest.php @@ -4,6 +4,7 @@ use Drupal\comment\Entity\Comment; use Drupal\comment\Entity\CommentType; +use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface; use Drupal\comment\Tests\CommentTestTrait; use Drupal\Component\Serialization\Json; use Drupal\Component\Utility\NestedArray; @@ -114,6 +115,7 @@ protected function createEntity() { $this->commentedEntity = EntityTest::create([ 'name' => 'Camelids', 'type' => 'bar', + 'comment' => CommentItemInterface::OPEN, ]); $this->commentedEntity->save();