diff --git a/core/modules/comment/config/schema/comment.schema.yml b/core/modules/comment/config/schema/comment.schema.yml index 86db110dcec3b22758d01543b97417faa51c9f3f..b5bcd86f6791dbc6688faf7a7e7de9e71d5ad82b 100644 --- a/core/modules/comment/config/schema/comment.schema.yml +++ b/core/modules/comment/config/schema/comment.schema.yml @@ -98,7 +98,7 @@ field.comment.field_settings: label: 'Comment settings' mapping: default_mode: - type: boolean + type: integer label: 'Threading' per_page: type: integer diff --git a/core/modules/comment/src/CommentViewBuilder.php b/core/modules/comment/src/CommentViewBuilder.php index cd36bc4efb9327627c7ef4816bbca47bd89e1f34..524349d135d80b0ac7b65dc1c77e20648ddc5fe9 100644 --- a/core/modules/comment/src/CommentViewBuilder.php +++ b/core/modules/comment/src/CommentViewBuilder.php @@ -8,6 +8,7 @@ namespace Drupal\comment; use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface; +use Drupal\Component\Utility\NestedArray; use Drupal\Core\Access\CsrfTokenGenerator; use Drupal\Core\Entity\Display\EntityViewDisplayInterface; use Drupal\Core\Entity\EntityInterface; @@ -66,6 +67,23 @@ public function __construct(EntityTypeInterface $entity_type, EntityManagerInter $this->csrfToken = $csrf_token; } + /** + * {@inheritdoc} + */ + protected function getBuildDefaults(EntityInterface $entity, $view_mode, $langcode) { + $build = parent::getBuildDefaults($entity, $view_mode, $langcode); + + // If threading is enabled, don't render cache individual comments, but do + // keep the cache tags, so they can bubble up. + if ($entity->getCommentedEntity()->getFieldDefinition($entity->getFieldName())->getSetting('default_mode') === CommentManagerInterface::COMMENT_MODE_THREADED) { + $cache_tags = $build['#cache']['tags']; + $build['#cache'] = []; + $build['#cache']['tags'] = $cache_tags; + } + + return $build; + } + /** * Overrides Drupal\Core\Entity\EntityViewBuilder::buildComponents(). * diff --git a/core/modules/comment/src/Tests/CommentCacheTagsTest.php b/core/modules/comment/src/Tests/CommentCacheTagsTest.php index f7bd90e17fb343ca88dbe3689b831fbef7fafcbb..ee69cc01cfe118671c91a3fcd89214504ece90ea 100644 --- a/core/modules/comment/src/Tests/CommentCacheTagsTest.php +++ b/core/modules/comment/src/Tests/CommentCacheTagsTest.php @@ -7,7 +7,9 @@ namespace Drupal\comment\Tests; +use Drupal\comment\CommentManagerInterface; use Drupal\Core\Entity\EntityInterface; +use Drupal\field\Entity\FieldConfig; use Drupal\system\Tests\Entity\EntityWithUriCacheTagsTestBase; /** @@ -44,7 +46,12 @@ protected function createEntity() { entity_test_create_bundle($bundle, NULL, 'entity_test'); // Create a comment field on this bundle. - \Drupal::service('comment.manager')->addDefaultField('entity_test', 'bar'); + \Drupal::service('comment.manager')->addDefaultField('entity_test', 'bar', 'comment'); + + // Display comments in a flat list; threaded comments are not render cached. + $field = FieldConfig::loadByName('entity_test', 'bar', 'comment'); + $field->settings['default_mode'] = CommentManagerInterface::COMMENT_MODE_FLAT; + $field->save(); // Create a "Camelids" test entity. $entity_test = entity_create('entity_test', array( @@ -77,7 +84,11 @@ protected function createEntity() { */ protected function getAdditionalCacheTagsForEntity(EntityInterface $entity) { /** @var \Drupal\comment\CommentInterface $entity */ - return array('filter_format:plain_text', 'user:' . $entity->getOwnerId(), 'user_view:1'); + return array( + 'filter_format:plain_text', + 'user:' . $entity->getOwnerId(), + 'user_view:1', + ); } } diff --git a/core/modules/comment/src/Tests/CommentTestBase.php b/core/modules/comment/src/Tests/CommentTestBase.php index 9b9f507f934842b7e628e7ec574a607d76549da7..d86e3d4a6dc38450d1d3f89ca391b7ece5282df6 100644 --- a/core/modules/comment/src/Tests/CommentTestBase.php +++ b/core/modules/comment/src/Tests/CommentTestBase.php @@ -184,11 +184,12 @@ public function postComment($entity, $comment, $subject = '', $contact = NULL, $ */ function commentExists(CommentInterface $comment = NULL, $reply = FALSE) { if ($comment) { - $regex = '/' . ($reply ? '
(.*?)' : ''); + $regex = '!' . ($reply ? '
(.*?)' : ''); $regex .= 'getSubject() . '(.*?)'; $regex .= $comment->comment_body->value . '(.*?)'; - $regex .= '/s'; + $regex .= ($reply ? '\s
(.*?)' : ''); + $regex .= '!s'; return (boolean) preg_match($regex, $this->drupalGetContent()); } diff --git a/core/modules/comment/src/Tests/CommentThreadingTest.php b/core/modules/comment/src/Tests/CommentThreadingTest.php index 476e3c991a1f245fba5c4cb0ef893a213255241e..6fa11979f84002bf5226e9e7419f1af3a7dc403e 100644 --- a/core/modules/comment/src/Tests/CommentThreadingTest.php +++ b/core/modules/comment/src/Tests/CommentThreadingTest.php @@ -35,6 +35,7 @@ function testCommentThreading() { $this->drupalLogin($this->web_user); $subject_text = $this->randomMachineName(); $comment_text = $this->randomMachineName(); + $comment1 = $this->postComment($this->node, $comment_text, $subject_text, TRUE); // Confirm that the comment was created and has the correct threading. $this->assertTrue($this->commentExists($comment1), 'Comment #1. Comment found.'); @@ -42,74 +43,85 @@ function testCommentThreading() { // Confirm that there is no reference to a parent comment. $this->assertNoParentLink($comment1->id()); - // Reply to comment #1 creating comment #2. - $this->drupalLogin($this->web_user); + // Post comment #2 following the comment #1 to test if it correctly jumps + // out the indentation in case there is a thread above. + $subject_text = $this->randomMachineName(); + $comment_text = $this->randomMachineName(); + $this->postComment($this->node, $comment_text, $subject_text, TRUE); + + // Reply to comment #1 creating comment #1_3. $this->drupalGet('comment/reply/node/' . $this->node->id() . '/comment/' . $comment1->id()); - $comment2 = $this->postComment(NULL, $this->randomMachineName(), '', TRUE); + $comment1_3 = $this->postComment(NULL, $this->randomMachineName(), '', TRUE); + // Confirm that the comment was created and has the correct threading. - $this->assertTrue($this->commentExists($comment2, TRUE), 'Comment #2. Reply found.'); - $this->assertEqual($comment2->getThread(), '01.00/'); + $this->assertTrue($this->commentExists($comment1_3, TRUE), 'Comment #1_3. Reply found.'); + $this->assertEqual($comment1_3->getThread(), '01.00/'); // Confirm that there is a link to the parent comment. - $this->assertParentLink($comment2->id(), $comment1->id()); + $this->assertParentLink($comment1_3->id(), $comment1->id()); + + + // Reply to comment #1_3 creating comment #1_3_4. + $this->drupalGet('comment/reply/node/' . $this->node->id() . '/comment/' . $comment1_3->id()); + $comment1_3_4 = $this->postComment(NULL, $this->randomMachineName(), $this->randomMachineName(), TRUE); - // Reply to comment #2 creating comment #3. - $this->drupalGet('comment/reply/node/' . $this->node->id() . '/comment/' . $comment2->id()); - $comment3 = $this->postComment(NULL, $this->randomMachineName(), $this->randomMachineName(), TRUE); // Confirm that the comment was created and has the correct threading. - $this->assertTrue($this->commentExists($comment3, TRUE), 'Comment #3. Second reply found.'); - $this->assertEqual($comment3->getThread(), '01.00.00/'); + $this->assertTrue($this->commentExists($comment1_3_4, TRUE), 'Comment #1_3_4. Second reply found.'); + $this->assertEqual($comment1_3_4->getThread(), '01.00.00/'); // Confirm that there is a link to the parent comment. - $this->assertParentLink($comment3->id(), $comment2->id()); + $this->assertParentLink($comment1_3_4->id(), $comment1_3->id()); - // Reply to comment #1 creating comment #4. - $this->drupalLogin($this->web_user); + // Reply to comment #1 creating comment #1_5. $this->drupalGet('comment/reply/node/' . $this->node->id() . '/comment/' . $comment1->id()); - $comment4 = $this->postComment(NULL, $this->randomMachineName(), '', TRUE); + + $comment1_5 = $this->postComment(NULL, $this->randomMachineName(), '', TRUE); + // Confirm that the comment was created and has the correct threading. - $this->assertTrue($this->commentExists($comment4), 'Comment #4. Third reply found.'); - $this->assertEqual($comment4->getThread(), '01.01/'); + $this->assertTrue($this->commentExists($comment1_5), 'Comment #1_5. Third reply found.'); + $this->assertEqual($comment1_5->getThread(), '01.01/'); // Confirm that there is a link to the parent comment. - $this->assertParentLink($comment4->id(), $comment1->id()); + $this->assertParentLink($comment1_5->id(), $comment1->id()); - // Post comment #2 overall comment #5. + // Post comment #3 overall comment #5. $this->drupalLogin($this->web_user); $subject_text = $this->randomMachineName(); $comment_text = $this->randomMachineName(); + $comment5 = $this->postComment($this->node, $comment_text, $subject_text, TRUE); // Confirm that the comment was created and has the correct threading. $this->assertTrue($this->commentExists($comment5), 'Comment #5. Second comment found.'); - $this->assertEqual($comment5->getThread(), '02/'); + $this->assertEqual($comment5->getThread(), '03/'); // Confirm that there is no link to a parent comment. $this->assertNoParentLink($comment5->id()); - // Reply to comment #5 creating comment #6. - $this->drupalLogin($this->web_user); + // Reply to comment #5 creating comment #5_6. $this->drupalGet('comment/reply/node/' . $this->node->id() . '/comment/' . $comment5->id()); - $comment6 = $this->postComment(NULL, $this->randomMachineName(), '', TRUE); + $comment5_6 = $this->postComment(NULL, $this->randomMachineName(), '', TRUE); + // Confirm that the comment was created and has the correct threading. - $this->assertTrue($this->commentExists($comment6, TRUE), 'Comment #6. Reply found.'); - $this->assertEqual($comment6->getThread(), '02.00/'); + $this->assertTrue($this->commentExists($comment5_6, TRUE), 'Comment #6. Reply found.'); + $this->assertEqual($comment5_6->getThread(), '03.00/'); // Confirm that there is a link to the parent comment. - $this->assertParentLink($comment6->id(), $comment5->id()); + $this->assertParentLink($comment5_6->id(), $comment5->id()); + + // Reply to comment #5_6 creating comment #5_6_7. + $this->drupalGet('comment/reply/node/' . $this->node->id() . '/comment/' . $comment5_6->id()); + $comment5_6_7 = $this->postComment(NULL, $this->randomMachineName(), $this->randomMachineName(), TRUE); - // Reply to comment #6 creating comment #7. - $this->drupalGet('comment/reply/node/' . $this->node->id() . '/comment/' . $comment6->id()); - $comment7 = $this->postComment(NULL, $this->randomMachineName(), $this->randomMachineName(), TRUE); // Confirm that the comment was created and has the correct threading. - $this->assertTrue($this->commentExists($comment7, TRUE), 'Comment #7. Second reply found.'); - $this->assertEqual($comment7->getThread(), '02.00.00/'); + $this->assertTrue($this->commentExists($comment5_6_7, TRUE), 'Comment #5_6_7. Second reply found.'); + $this->assertEqual($comment5_6_7->getThread(), '03.00.00/'); // Confirm that there is a link to the parent comment. - $this->assertParentLink($comment7->id(), $comment6->id()); + $this->assertParentLink($comment5_6_7->id(), $comment5_6->id()); - // Reply to comment #5 creating comment #8. - $this->drupalLogin($this->web_user); + // Reply to comment #5 creating comment #5_8. $this->drupalGet('comment/reply/node/' . $this->node->id() . '/comment/' . $comment5->id()); - $comment8 = $this->postComment(NULL, $this->randomMachineName(), '', TRUE); + $comment5_8 = $this->postComment(NULL, $this->randomMachineName(), '', TRUE); + // Confirm that the comment was created and has the correct threading. - $this->assertTrue($this->commentExists($comment8), 'Comment #8. Third reply found.'); - $this->assertEqual($comment8->getThread(), '02.01/'); + $this->assertTrue($this->commentExists($comment5_8), 'Comment #5_8. Third reply found.'); + $this->assertEqual($comment5_8->getThread(), '03.01/'); // Confirm that there is a link to the parent comment. - $this->assertParentLink($comment8->id(), $comment5->id()); + $this->assertParentLink($comment5_8->id(), $comment5->id()); } /**