diff --git a/core/modules/comment/comment.install b/core/modules/comment/comment.install index b67825e..a4bbc9f 100644 --- a/core/modules/comment/comment.install +++ b/core/modules/comment/comment.install @@ -127,3 +127,30 @@ function comment_update_8001() { /** * @} End of "addtogroup updates-8.0.0-rc". */ + +/** + * Adds the new 'view_mode' setting to all view displays using the + * 'comment_default' formatter. + */ +function comment_update_8101() { + $config_factory = \Drupal::configFactory(); + // Iterate on all entity view displays. + foreach ($config_factory->listAll('core.entity_view_display.') as $name) { + $changed = FALSE; + $display = $config_factory->getEditable($name); + $components = $display->get('content') ?: []; + foreach ($components as $field_name => $component) { + if (isset($component['type']) && ($component['type'] === 'comment_default')) { + if (empty($display->get("content.{$field_name}.settings.view_mode"))) { + $display->set("content.{$field_name}.settings.view_mode", 'default'); + $changed = TRUE; + } + } + } + + if ($changed) { + $display->save(TRUE); + } + } + +} diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module index e333b56..1b2340b 100644 --- a/core/modules/comment/comment.module +++ b/core/modules/comment/comment.module @@ -14,6 +14,7 @@ use Drupal\comment\Entity\CommentType; use Drupal\Core\Entity\FieldableEntityInterface; use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface; +use Drupal\Core\Entity\Entity\EntityViewMode; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Routing\RouteMatchInterface; @@ -756,3 +757,43 @@ function comment_preprocess_field(&$variables) { function comment_ranking() { return \Drupal::service('comment.statistics')->getRankingInfo(); } + +/** + * Implements hook_ENTITY_TYPE_presave() for entity_view_display entities. + */ +function comment_entity_view_display_presave(EntityViewDisplayInterface $display) { + // Act only on comment view displays being disabled. + if ($display->isNew() || $display->getTargetEntityTypeId() != 'comment' || $display->status()) { + return; + } + $storage = \Drupal::entityTypeManager()->getStorage('entity_view_display'); + if (!$storage->loadUnchanged($display->getOriginalId())->status()) { + return; + } + + // Disable the comment field formatter when the used view display is disabled. + foreach ($storage->loadMultiple() as $id => $view_display) { + $changed = FALSE; + /** @var \Drupal\Core\Entity\Display\EntityViewDisplayInterface $view_display */ + foreach ($view_display->getComponents() as $field => $component) { + if (isset($component['type']) && ($component['type'] == 'comment_default')) { + if ($component['settings']['view_mode'] == $display->getMode()) { + $view_display->removeComponent($field); + /** @var \Drupal\Core\Entity\EntityViewModeInterface $mode */ + $mode = EntityViewMode::load($display->getTargetEntityTypeId() . '.' . $display->getMode()); + $arguments = [ + '@id' => $view_display->id(), + '@name' => $field, + '@display' => $mode->label(), + '@mode' => $display->getMode(), + ]; + \Drupal::logger('system')->warning("View display '@id': Comment field formatter '@name' was disabled because is using the comment view display '@display' (@mode) that was just disabled.", $arguments); + $changed = TRUE; + } + } + } + if ($changed) { + $view_display->save(); + } + } +} diff --git a/core/modules/comment/config/schema/comment.schema.yml b/core/modules/comment/config/schema/comment.schema.yml index d9f5a77..a55488a 100644 --- a/core/modules/comment/config/schema/comment.schema.yml +++ b/core/modules/comment/config/schema/comment.schema.yml @@ -4,6 +4,9 @@ field.formatter.settings.comment_default: type: mapping label: 'Comment display format settings' mapping: + view_mode: + type: string + label: 'The comment entity view mode to be used in this formatter' pager_id: type: integer label: 'Pager ID' diff --git a/core/modules/comment/src/Plugin/Field/FieldFormatter/CommentDefaultFormatter.php b/core/modules/comment/src/Plugin/Field/FieldFormatter/CommentDefaultFormatter.php index 64ff301..cdd68f6 100644 --- a/core/modules/comment/src/Plugin/Field/FieldFormatter/CommentDefaultFormatter.php +++ b/core/modules/comment/src/Plugin/Field/FieldFormatter/CommentDefaultFormatter.php @@ -8,6 +8,7 @@ namespace Drupal\comment\Plugin\Field\FieldFormatter; use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface; +use Drupal\Core\Entity\Entity\EntityViewDisplay; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Entity\EntityFormBuilderInterface; use Drupal\Core\Field\FieldItemListInterface; @@ -40,6 +41,7 @@ class CommentDefaultFormatter extends FormatterBase implements ContainerFactoryP */ public static function defaultSettings() { return array( + 'view_mode' => 'default', 'pager_id' => 0, ) + parent::defaultSettings(); } @@ -162,7 +164,7 @@ public function viewElements(FieldItemListInterface $items, $langcode) { $comments_per_page = $comment_settings['per_page']; $comments = $this->storage->loadThread($entity, $field_name, $mode, $comments_per_page, $this->getSetting('pager_id')); if ($comments) { - $build = $this->viewBuilder->viewMultiple($comments); + $build = $this->viewBuilder->viewMultiple($comments, $this->getSetting('view_mode')); $build['pager']['#type'] = 'pager'; if ($this->getSetting('pager_id')) { $build['pager']['#element'] = $this->getSetting('pager_id'); @@ -206,6 +208,23 @@ public function viewElements(FieldItemListInterface $items, $langcode) { */ public function settingsForm(array $form, FormStateInterface $form_state) { $element = array(); + $view_modes = $this->getViewModes(); + // Only show the select element when there are more than one options. + if (count($view_modes) > 1) { + $element['view_mode'] = [ + '#type' => 'select', + '#title' => $this->t('Comments view mode'), + '#description' => $this->t('Select the view mode used to show the list of comments.'), + '#default_value' => $this->getSetting('view_mode'), + '#options' => $view_modes, + ]; + } + else { + $element['view_mode'] = [ + '#type' => 'value', + '#value' => 'default', + ]; + } $element['pager_id'] = array( '#type' => 'select', '#title' => $this->t('Pager ID'), @@ -220,13 +239,41 @@ public function settingsForm(array $form, FormStateInterface $form_state) { * {@inheritdoc} */ public function settingsSummary() { - // Only show a summary if we're using a non-standard pager id. - if ($this->getSetting('pager_id')) { - return array($this->t('Pager ID: @id', array( - '@id' => $this->getSetting('pager_id'), - ))); + $view_mode = $this->getSetting('view_mode'); + $view_modes = $this->getViewModes(); + $view_mode_label = isset($view_modes[$view_mode]) ? $view_modes[$view_mode] : 'default'; + $summary = [$this->t('Comment view mode: @mode', ['@mode' => $view_mode_label])]; + if ($pager_id = $this->getSetting('pager_id')) { + $summary[] = $this->t('Pager ID: @id', ['@id' => $pager_id]); } - return array(); + return $summary; + } + + /** + * {@inheritdoc} + */ + public function calculateDependencies() { + $dependencies = parent::calculateDependencies(); + if ($mode = $this->getSetting('view_mode')) { + if ($bundle = $this->getFieldSetting('comment_type')) { + /** @var \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display */ + if ($display = EntityViewDisplay::load("comment.$bundle.$mode")) { + $dependencies[$display->getConfigDependencyKey()][] = $display->getConfigDependencyName(); + } + } + } + return $dependencies; + } + + /** + * Provides a list of comment view modes for the configured comment type. + * + * @return array + * Associative array keyed by view mode key and having the view mode label + * as value. + */ + protected function getViewModes() { + return $this->entityManager->getViewModeOptionsByBundle('comment', $this->getFieldSetting('comment_type')); } } diff --git a/core/modules/comment/src/Tests/CommentInterfaceTest.php b/core/modules/comment/src/Tests/CommentInterfaceTest.php index 4b326a6..bea911f 100644 --- a/core/modules/comment/src/Tests/CommentInterfaceTest.php +++ b/core/modules/comment/src/Tests/CommentInterfaceTest.php @@ -10,6 +10,9 @@ use Drupal\comment\CommentManagerInterface; use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface; use Drupal\comment\Entity\Comment; +use Drupal\Component\Utility\Unicode; +use Drupal\Core\Entity\Entity\EntityViewDisplay; +use Drupal\Core\Entity\Entity\EntityViewMode; use Drupal\user\RoleInterface; use Drupal\filter\Entity\FilterFormat; @@ -291,4 +294,54 @@ public function testAutoFilledHtmlSubject() { $this->assertEqual('(No subject)', Comment::load(2)->getSubject()); } + /** + * Tests the comment field formatter used with non-default comment entity view + * mode. + */ + public function testViewMode() { + $this->drupalLogin($this->webUser); + $this->drupalGet($this->node->toUrl()); + $comment_text = $this->randomMachineName(); + // Post a comment. + $this->postComment($this->node, $comment_text); + + // Comment displayed in 'default' display mode found and has body text. + $comment_element = $this->cssSelect('.comment-wrapper'); + $this->assertTrue(!empty($comment_element)); + $this->assertRaw('

' . $comment_text . '

'); + + // Create a new comment entity view mode. + $mode = Unicode::strtolower($this->randomMachineName()); + EntityViewMode::create([ + 'targetEntityType' => 'comment', + 'id' => "comment.$mode", + ])->save(); + // Create the corresponding entity view display for article node-type. Note + // that this new view display mode doesn't contain the comment body. + EntityViewDisplay::create([ + 'targetEntityType' => 'comment', + 'bundle' => 'comment', + 'mode' => $mode, + ])->setStatus(TRUE)->save(); + + /** @var \Drupal\Core\Entity\Display\EntityViewDisplayInterface $node_display */ + $node_display = EntityViewDisplay::load('node.article.default'); + $formatter = $node_display->getComponent('comment'); + // Change the node comment field formatter to use $mode mode instead of + // 'default' mode. + $formatter['settings']['view_mode'] = $mode; + $node_display + ->setComponent('comment', $formatter) + ->save(); + + // Reloading the node page to show the same node with its same comment but + // with a different display mode. + $this->drupalGet($this->node->toUrl()); + // The comment should exist but without the body text because we used $mode + // mode this time. + $comment_element = $this->cssSelect('.comment-wrapper'); + $this->assertTrue(!empty($comment_element)); + $this->assertNoRaw('

' . $comment_text . '

'); + } + } diff --git a/core/modules/comment/src/Tests/CommentPagerTest.php b/core/modules/comment/src/Tests/CommentPagerTest.php index 9061f64..14cd3b5 100644 --- a/core/modules/comment/src/Tests/CommentPagerTest.php +++ b/core/modules/comment/src/Tests/CommentPagerTest.php @@ -288,6 +288,7 @@ function testTwoPagers() { 'weight' => 30, 'settings' => array( 'pager_id' => 1, + 'view_mode' => 'default', ) )) ->save(); diff --git a/core/modules/comment/src/Tests/CommentTestTrait.php b/core/modules/comment/src/Tests/CommentTestTrait.php index d8c54c2..72c6c35 100644 --- a/core/modules/comment/src/Tests/CommentTestTrait.php +++ b/core/modules/comment/src/Tests/CommentTestTrait.php @@ -34,8 +34,11 @@ * CommentItemInterface::OPEN. * @param string $comment_type_id * (optional) ID of comment type to use. Defaults to 'comment'. + * @param string $comment_view_mode + * (optional) The comment view mode to be used in comment field formatter. + * Defaults to 'full'. */ - public function addDefaultCommentField($entity_type, $bundle, $field_name = 'comment', $default_value = CommentItemInterface::OPEN, $comment_type_id = 'comment') { + public function addDefaultCommentField($entity_type, $bundle, $field_name = 'comment', $default_value = CommentItemInterface::OPEN, $comment_type_id = 'comment', $comment_view_mode = 'full') { $entity_manager = \Drupal::entityManager(); // Create the comment type if needed. $comment_type_storage = $entity_manager->getStorage('comment_type'); @@ -111,6 +114,7 @@ public function addDefaultCommentField($entity_type, $bundle, $field_name = 'com 'label' => 'above', 'type' => 'comment_default', 'weight' => 20, + 'settings' => array('view_mode' => $comment_view_mode), )) ->save(); foreach ($entity_manager->getViewModes($entity_type) as $id => $view_mode) { diff --git a/core/modules/comment/src/Tests/Update/CommentUpdateTest.php b/core/modules/comment/src/Tests/Update/CommentUpdateTest.php new file mode 100644 index 0000000..db1cb43 --- /dev/null +++ b/core/modules/comment/src/Tests/Update/CommentUpdateTest.php @@ -0,0 +1,47 @@ +databaseDumpFiles = [ + __DIR__ . '/../../../../system/tests/fixtures/update/drupal-8-rc1.bare.standard.php.gz', + ]; + } + + /** + * Tests comment_update_8101(). + * + * @see comment_update_8101() + */ + public function testCommentUpdate8101() { + // Load the 'node.article.default' entity view display config, and check + // that component 'comment' does not contain the 'view_mode' setting. + $config = $this->config('core.entity_view_display.node.article.default'); + $this->assertNull($config->get('content.comment.settings.view_mode')); + + // Run updates. + $this->runUpdates(); + + // Reload the config, and check that 'view_mode' has the value 'default'. + $config = $this->config('core.entity_view_display.node.article.default'); + $this->assertIdentical($config->get('content.comment.settings.view_mode'), 'default'); + } + +} diff --git a/core/modules/comment/tests/src/Kernel/CommentIntegrationTest.php b/core/modules/comment/tests/src/Kernel/CommentIntegrationTest.php new file mode 100644 index 0000000..efde8dd --- /dev/null +++ b/core/modules/comment/tests/src/Kernel/CommentIntegrationTest.php @@ -0,0 +1,142 @@ +installEntitySchema('entity_test'); + $this->installEntitySchema('user'); + $this->installEntitySchema('comment'); + $this->installSchema('dblog', ['watchdog']); + + // Create a new 'comment' comment-type. + CommentType::create([ + 'id' => 'comment', + 'label' => $this->randomString(), + ])->save(); + } + + /** + * Tests view mode setting integration. + * + * @see comment_entity_view_display_presave() + * @see CommentDefaultFormatter::calculateDependencies() + */ + public function testViewMode() { + $mode = Unicode::strtolower($this->randomMachineName()); + // Create a new comment view mode and a view display entity. + EntityViewMode::create([ + 'id' => "comment.$mode", + 'targetEntityType' => 'comment', + 'settings' => ['comment_type' => 'comment'], + ])->save(); + EntityViewDisplay::create([ + 'targetEntityType' => 'comment', + 'bundle' => 'comment', + 'mode' => $mode, + ])->setStatus(TRUE)->save(); + + // Create a comment field attached to a host 'entity_test' entity. + FieldStorageConfig::create([ + 'entity_type' => 'entity_test', + 'type' => 'comment', + 'field_name' => $field_name = Unicode::strtolower($this->randomMachineName()), + 'settings' => [ + 'comment_type' => 'comment', + ], + ])->save(); + FieldConfig::create([ + 'entity_type' => 'entity_test', + 'bundle' => 'entity_test', + 'field_name' => $field_name, + ])->save(); + + $component = [ + 'type' => 'comment_default', + 'settings' => ['view_mode' => $mode, 'pager_id' => 0], + ]; + // Create a new 'entity_test' view display on host entity that uses the + // custom comment display in field formatter to show the field. + EntityViewDisplay::create([ + 'targetEntityType' => 'entity_test', + 'bundle' => 'entity_test', + 'mode' => 'default' + ])->setComponent($field_name, $component)->setStatus(TRUE)->save(); + + $host_display_id = 'entity_test.entity_test.default'; + $comment_display_id = "comment.comment.$mode"; + + // Disable the "comment.comment.$mode" display. + EntityViewDisplay::load($comment_display_id)->setStatus(FALSE)->save(); + + /** @var \Drupal\Core\Entity\Display\EntityViewDisplayInterface $host_display */ + $host_display = EntityViewDisplay::load($host_display_id); + + // Check that the field formatter has been disabled on host view display. + $this->assertNull($host_display->getComponent($field_name)); + $this->assertTrue($host_display->get('hidden')[$field_name]); + + // Check that the proper warning has been logged. + $arguments = [ + '@id' => $host_display_id, + '@name' => $field_name, + '@display' => EntityViewMode::load("comment.$mode")->label(), + '@mode' => $mode, + ]; + $logged = (bool) Database::getConnection()->select('watchdog') + ->fields('watchdog', ['wid']) + ->condition('type', 'system') + ->condition('message', "View display '@id': Comment field formatter '@name' was disabled because is using the comment view display '@display' (@mode) that was just disabled.") + ->condition('variables', serialize($arguments)) + ->execute() + ->fetchField(); + + // Re-enable the comment view display. + EntityViewDisplay::load($comment_display_id)->setStatus(TRUE)->save(); + // Re-enable the comment field formatter on host entity view display. + EntityViewDisplay::load($host_display_id)->setComponent($field_name, $component)->save(); + + // Delete the "comment.$mode" view mode. + EntityViewMode::load("comment.$mode")->delete(); + + // Check that the comment view display entity has been deleted too. + $this->assertNull(EntityViewDisplay::load($comment_display_id)); + + /** @var \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display */ + $host_display = EntityViewDisplay::load($host_display_id); + + // Check that the field formatter has been disabled on host view display. + $this->assertNull($host_display->getComponent($field_name)); + $this->assertTrue($host_display->get('hidden')[$field_name]); + } + +} diff --git a/core/modules/forum/config/install/core.entity_view_display.node.forum.default.yml b/core/modules/forum/config/install/core.entity_view_display.node.forum.default.yml index 39389a5..b157c83 100644 --- a/core/modules/forum/config/install/core.entity_view_display.node.forum.default.yml +++ b/core/modules/forum/config/install/core.entity_view_display.node.forum.default.yml @@ -2,6 +2,7 @@ langcode: en status: true dependencies: config: + - core.entity_view_display.comment.comment_forum.default - field.field.node.forum.body - field.field.node.forum.comment_forum - field.field.node.forum.taxonomy_forums @@ -26,6 +27,7 @@ content: type: comment_default weight: 20 settings: + view_mode: default pager_id: 0 third_party_settings: { } links: diff --git a/core/profiles/standard/config/install/core.entity_view_display.node.article.default.yml b/core/profiles/standard/config/install/core.entity_view_display.node.article.default.yml index e0d3782..ca59894 100644 --- a/core/profiles/standard/config/install/core.entity_view_display.node.article.default.yml +++ b/core/profiles/standard/config/install/core.entity_view_display.node.article.default.yml @@ -2,6 +2,7 @@ langcode: en status: true dependencies: config: + - core.entity_view_display.comment.comment.default - field.field.node.article.body - field.field.node.article.comment - field.field.node.article.field_image @@ -24,10 +25,11 @@ content: third_party_settings: { } label: hidden comment: - label: above type: comment_default - weight: 20 + weight: 110 + label: above settings: + view_mode: default pager_id: 0 third_party_settings: { } field_image: @@ -45,13 +47,6 @@ content: settings: link: true third_party_settings: { } - comment: - label: above - type: comment_default - weight: 110 - settings: - pager_id: 0 - third_party_settings: { } links: weight: 100 hidden: