diff --git a/core/modules/comment/src/CommentLinkBuilder.php b/core/modules/comment/src/CommentLinkBuilder.php index 8c074da..6038f37 100644 --- a/core/modules/comment/src/CommentLinkBuilder.php +++ b/core/modules/comment/src/CommentLinkBuilder.php @@ -7,9 +7,11 @@ namespace Drupal\comment; +use Drupal\comment\Plugin\Field\FieldFormatter\CommentDefaultFormatter; use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface; use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Entity\EntityManagerInterface; +use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; @@ -92,159 +94,180 @@ public function buildCommentedEntityLinks(ContentEntityInterface $entity, array if (!$entity->hasField($field_name)) { continue; } - $links = array(); - $commenting_status = $entity->get($field_name)->status; - if ($commenting_status != CommentItemInterface::HIDDEN) { - // Entity has commenting status open or closed. - // Get formatter settings through EntityViewDisplay (logic copied from - // entity_get_display()). + // Get the field formatter, via the entity display. + $display = $this->entityManager->getStorage('entity_view_display') + ->load($entity->getEntityTypeId() . '.' . $entity->bundle() . '.' . $view_mode); + if (!$display) { $display = $this->entityManager->getStorage('entity_view_display') - ->load($entity->getEntityTypeId() . '.' . $entity->bundle() . '.' . $view_mode); - if (!$display) { - $display = $this->entityManager->getStorage('entity_view_display') - ->create(array( - 'targetEntityType' => $entity->getEntityTypeId(), - 'bundle' => $entity->bundle(), - 'mode' => $view_mode, - 'status' => TRUE, - )); - } - $display_settings = $display->getComponent($field_name); + ->create(array( + 'targetEntityType' => $entity->getEntityTypeId(), + 'bundle' => $entity->bundle(), + 'mode' => $view_mode, + 'status' => TRUE, + )); + } + $formatter_options = $display->getComponent($field_name); + $links = $this->buildCommentedEntityFieldLinks($field_name, $entity->get($field_name), $formatter_options['settings']); + if (!empty($links)) { + $entity_links['comment__' . $field_name] = $links; + } + } + return $entity_links; + } + + /** + * {@inheritdoc} + */ + public function buildCommentedEntityFieldLinks($field_name, FieldItemListInterface $items, array $display_settings) { + $build = array(); + + $commenting_status = $items->status; + if ($commenting_status == CommentItemInterface::HIDDEN) { + return $build; + } + // Entity has commenting status open or closed. + + $link_style = $display_settings['show_links']; + if ($link_style == CommentDefaultFormatter::LINKS_NONE) { + return $build; + } - if ($view_mode == 'rss') { - // Add a comments RSS element which is a URL to the comments of this - // entity. - $options = array( + $entity = $items->getEntity(); + if ($link_style == CommentDefaultFormatter::LINKS_RSS) { + // Add a comments RSS element which is a URL to the comments of this + // entity. + $options = array( + 'fragment' => 'comments', + 'absolute' => TRUE, + ); + $entity->rss_elements[] = array( + 'key' => 'comments', + 'value' => $entity->url('canonical', $options), + ); + } + elseif ($link_style == CommentDefaultFormatter::LINKS_TEASER) { + // Teaser style links: display the number of comments that have been posted, + // or a link to add new comments if the user has permission, the entity + // is open to new comments, and there currently are none. + if ($this->currentUser->hasPermission('access comments')) { + if (!empty($items->comment_count)) { + $links['comment-comments'] = array( + 'title' => $this->formatPlural($items->comment_count, '1 comment', '@count comments'), + 'attributes' => array('title' => $this->t('Jump to the first comment of this posting.')), 'fragment' => 'comments', - 'absolute' => TRUE, + ) + $entity->urlInfo()->toArray(); + if ($this->moduleHandler->moduleExists('history')) { + $links['comment-new-comments'] = array( + 'title' => '', + 'href' => '', + 'attributes' => array( + 'class' => 'hidden', + 'title' => t('Jump to the first new comment of this posting.'), + 'data-history-node-last-comment-timestamp' => $items->last_comment_timestamp, + 'data-history-node-field-name' => $field_name, + 'data-comment-default-mode' => $display_settings['default_mode'], + 'data-comment-per-page' => $display_settings['per_page'], + ), + ); + } + } + } + // Provide a link to new comment form. + if ($commenting_status == CommentItemInterface::OPEN) { + $comment_form_location = $display_settings['form_location']; + if ($this->currentUser->hasPermission('post comments')) { + $links['comment-add'] = array( + 'title' => t('Add new comment'), + 'language' => $entity->language(), + 'attributes' => array('title' => t('Add a new comment to this page.')), + 'fragment' => 'comment-form', ); - $entity->rss_elements[] = array( - 'key' => 'comments', - 'value' => $entity->url('canonical', $options), + if ($comment_form_location == CommentItemInterface::FORM_SEPARATE_PAGE) { + $links['comment-add']['route_name'] = 'comment.reply'; + $links['comment-add']['route_parameters'] = array( + 'entity_type' => $entity->getEntityTypeId(), + 'entity_id' => $entity->id(), + 'field_name' => $field_name, + ); + } + else { + $links['comment-add'] += $entity->urlInfo()->toArray(); + } + } + elseif ($this->currentUser->isAnonymous()) { + $links['comment-forbidden'] = array( + 'title' => $this->commentManager->forbiddenMessage($entity, $field_name), + 'html' => TRUE, ); } - elseif ($view_mode == 'teaser') { - // Teaser view: display the number of comments that have been posted, - // or a link to add new comments if the user has permission, the - // entity is open to new comments, and there currently are none. - if ($this->currentUser->hasPermission('access comments')) { - if (!empty($entity->get($field_name)->comment_count)) { - $links['comment-comments'] = array( - 'title' => $this->formatPlural($entity->get($field_name)->comment_count, '1 comment', '@count comments'), - 'attributes' => array('title' => $this->t('Jump to the first comment of this posting.')), - 'fragment' => 'comments', - ) + $entity->urlInfo()->toArray(); - if ($this->moduleHandler->moduleExists('history')) { - $links['comment-new-comments'] = array( - 'title' => '', - 'href' => '', - 'attributes' => array( - 'class' => 'hidden', - 'title' => $this->t('Jump to the first new comment of this posting.'), - 'data-history-node-last-comment-timestamp' => $entity->get($field_name)->last_comment_timestamp, - 'data-history-node-field-name' => $field_name, - ), - ); - } - } - } - // Provide a link to new comment form. - if ($commenting_status == CommentItemInterface::OPEN) { - $comment_form_location = $display_settings['settings']['form_location']; - - if ($this->currentUser->hasPermission('post comments')) { - $links['comment-add'] = array( - 'title' => $this->t('Add new comment'), - 'language' => $entity->language(), - 'attributes' => array('title' => $this->t('Add a new comment to this page.')), - 'fragment' => 'comment-form', + } + } + else { + // Default links: add a "post comment" link if the user is allowed to + // post comments and if this node is allowing new comments. + if ($commenting_status == CommentItemInterface::OPEN) { + $comment_form_location = $display_settings['form_location']; + if ($this->currentUser->hasPermission('post comments')) { + // Show the "post comment" link if the form is on another page, or + // if there are existing comments that the link will skip past. + if ($comment_form_location == CommentItemInterface::FORM_SEPARATE_PAGE || (!empty($items->comment_count) && $this->currentUser->hasPermission('access comments'))) { + $links['comment-add'] = array( + 'title' => t('Add new comment'), + 'attributes' => array('title' => t('Share your thoughts and opinions related to this posting.')), + 'fragment' => 'comment-form', + ); + if ($comment_form_location == CommentItemInterface::FORM_SEPARATE_PAGE) { + $links['comment-add']['route_name'] = 'comment.reply'; + $links['comment-add']['route_parameters'] = array( + 'entity_type' => $entity->getEntityTypeId(), + 'entity_id' => $entity->id(), + 'field_name' => $field_name, ); - if ($comment_form_location == CommentItemInterface::FORM_SEPARATE_PAGE) { - $links['comment-add']['route_name'] = 'comment.reply'; - $links['comment-add']['route_parameters'] = array( - 'entity_type' => $entity->getEntityTypeId(), - 'entity' => $entity->id(), - 'field_name' => $field_name, - ); - } - else { - $links['comment-add'] += $entity->urlInfo()->toArray(); - } } - elseif ($this->currentUser->isAnonymous()) { - $links['comment-forbidden'] = array( - 'title' => $this->commentManager->forbiddenMessage($entity, $field_name), - 'html' => TRUE, - ); + else { + $links['comment-add'] += $entity->urlInfo()->toArray(); } } } - else { - // Entity in other view modes: add a "post comment" link if the user - // is allowed to post comments and if this entity is allowing new - // comments. - if ($commenting_status == CommentItemInterface::OPEN) { - $comment_form_location = $display_settings['settings']['form_location']; - if ($this->currentUser->hasPermission('post comments')) { - // Show the "post comment" link if the form is on another page, or - // if there are existing comments that the link will skip past. - if ($comment_form_location == CommentItemInterface::FORM_SEPARATE_PAGE || (!empty($entity->get($field_name)->comment_count) && $this->currentUser->hasPermission('access comments'))) { - $links['comment-add'] = array( - 'title' => $this->t('Add new comment'), - 'attributes' => array('title' => $this->t('Share your thoughts and opinions related to this posting.')), - 'fragment' => 'comment-form', - ); - if ($comment_form_location == CommentItemInterface::FORM_SEPARATE_PAGE) { - $links['comment-add']['route_name'] = 'comment.reply'; - $links['comment-add']['route_parameters'] = array( - 'entity_type' => $entity->getEntityTypeId(), - 'entity' => $entity->id(), - 'field_name' => $field_name, - ); - } - else { - $links['comment-add'] += $entity->urlInfo()->toArray(); - } - } - } - elseif ($this->currentUser->isAnonymous()) { - $links['comment-forbidden'] = array( - 'title' => $this->commentManager->forbiddenMessage($entity, $field_name), - 'html' => TRUE, - ); - } - } + elseif ($this->currentUser->isAnonymous()) { + $links['comment-forbidden'] = array( + 'title' => $this->commentManager->forbiddenMessage($entity, $field_name), + 'html' => TRUE, + ); } } + } - if (!empty($links)) { - $entity_links['comment__' . $field_name] = array( - '#theme' => 'links__entity__comment__' . $field_name, - '#links' => $links, - '#attributes' => array('class' => array('links', 'inline')), - ); - if ($view_mode == 'teaser' && $this->moduleHandler->moduleExists('history') && $this->currentUser->isAuthenticated()) { - $entity_links['comment__' . $field_name]['#attached']['library'][] = 'comment/drupal.node-new-comments-link'; + if (!empty($links)) { + $build = array( + '#theme' => 'links__entity__comment__' . $field_name, + '#links' => $links, + '#attributes' => array('class' => array('links', 'inline')), + ); + if ($link_style == CommentDefaultFormatter::LINKS_TEASER && $this->moduleHandler->moduleExists('history') && $this->currentUser->isAuthenticated() + // @todo revisit this condition when history.module is generalized; + // see https://www.drupal.org/node/2081585. + && $entity->getEntityTypeId() == 'node') { + $build['#attached']['library'][] = 'comment/drupal.node-new-comments-link'; - // Embed the metadata for the "X new comments" link (if any) on this - // entity. - $entity_links['comment__' . $field_name]['#post_render_cache']['history_attach_timestamp'] = array( - array('node_id' => $entity->id()), - ); - $entity_links['comment__' . $field_name]['#post_render_cache']['Drupal\comment\CommentViewBuilder::attachNewCommentsLinkMetadata'] = array( - array( - 'entity_type' => $entity->getEntityTypeId(), - 'entity_id' => $entity->id(), - 'field_name' => $field_name, - 'default_mode' => $display_settings['settings']['default_mode'], - 'per_page' =>$display_settings['settings']['per_page'], - ), - ); - } + // Embed the metadata for the "X new comments" link (if any) on this + // node. + $build['#post_render_cache']['history_attach_timestamp'] = array( + array($entity->getEntityTypeId() . '_id' => $entity->id()), + ); + $build['#post_render_cache']['Drupal\comment\CommentViewBuilder::attachNewCommentsLinkMetadata'] = array( + array( + 'entity_type' => $entity->getEntityTypeId(), + 'entity_id' => $entity->id(), + 'field_name' => $field_name, + 'default_mode' => $display_settings['default_mode'], + 'per_page' => $display_settings['per_page'], + ), + ); } } - return $entity_links; + return $build; } } diff --git a/core/modules/comment/src/CommentLinkBuilderInterface.php b/core/modules/comment/src/CommentLinkBuilderInterface.php index 995efcf..97f3193 100644 --- a/core/modules/comment/src/CommentLinkBuilderInterface.php +++ b/core/modules/comment/src/CommentLinkBuilderInterface.php @@ -8,6 +8,7 @@ namespace Drupal\comment; use Drupal\Core\Entity\ContentEntityInterface; +use Drupal\Core\Field\FieldItemListInterface; /** * Defines an interface for building comment links on a commented entity. @@ -25,8 +26,24 @@ * Array of context passed from the entity view builder. * * @return array - * Array of entity links. + * Array of entity links (separately grouped per comment field). */ public function buildCommentedEntityLinks(ContentEntityInterface $entity, array &$context); + /** + * Builds links for one comment field on an entity. + * + * @param string $field_name + * Machine name of the comment field + * @param FieldItemListInterface $items + * Value of the comment field + * @param array $display_settings + * The formatter settings for the comment field in the desired view mode. + * (That is: the 'settings' sub-array of the field's display options.) + * + * @return array + * A render array of entity links for one field. + */ + public function buildCommentedEntityFieldLinks($field_name, FieldItemListInterface $items, array $display_settings); + } diff --git a/core/modules/comment/src/Plugin/Field/FieldFormatter/CommentDefaultFormatter.php b/core/modules/comment/src/Plugin/Field/FieldFormatter/CommentDefaultFormatter.php index f2c3ebe..acd41b5 100644 --- a/core/modules/comment/src/Plugin/Field/FieldFormatter/CommentDefaultFormatter.php +++ b/core/modules/comment/src/Plugin/Field/FieldFormatter/CommentDefaultFormatter.php @@ -7,6 +7,7 @@ namespace Drupal\comment\Plugin\Field\FieldFormatter; +use Drupal\comment\CommentLinkBuilderInterface; use Drupal\comment\CommentManagerInterface; use Drupal\comment\CommentStorageInterface; use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface; @@ -114,6 +115,13 @@ public static function defaultSettings() { protected $commentManager; /** + * The link builder service. + * + * @var \Drupal\comment\CommentLinkBuilderInterface + */ + protected $commentLinkBuilder; + + /** * {@inheritdoc} */ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { @@ -130,7 +138,8 @@ public static function create(ContainerInterface $container, array $configuratio $container->get('entity.manager')->getViewBuilder('comment'), $container->get('entity.form_builder'), $container->get('module_handler'), - $container->get('comment.manager') + $container->get('comment.manager'), + $container->get('comment.link_builder') ); } @@ -163,8 +172,10 @@ public static function create(ContainerInterface $container, array $configuratio * The module handler service. * @param \Drupal\comment\CommentManagerInterface $comment_manager * The comment manager service. + * @param \Drupal\comment\CommentLinkBuilderInterface $comment_link_builder + * The link builder service. */ - public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, AccountInterface $current_user, CommentStorageInterface $comment_storage, EntityViewBuilderInterface $comment_view_builder, EntityFormBuilderInterface $entity_form_builder, ModuleHandlerInterface $module_handler, CommentManagerInterface $comment_manager) { + public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, AccountInterface $current_user, CommentStorageInterface $comment_storage, EntityViewBuilderInterface $comment_view_builder, EntityFormBuilderInterface $entity_form_builder, ModuleHandlerInterface $module_handler, CommentManagerInterface $comment_manager, CommentLinkBuilderInterface $comment_link_builder) { parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings); $this->viewBuilder = $comment_view_builder; $this->storage = $comment_storage; @@ -172,6 +183,7 @@ public function __construct($plugin_id, $plugin_definition, FieldDefinitionInter $this->entityFormBuilder = $entity_form_builder; $this->moduleHandler = $module_handler; $this->commentManager = $comment_manager; + $this->commentLinkBuilder = $comment_link_builder; } /** @@ -249,12 +261,16 @@ public function viewElements(FieldItemListInterface $items) { } } + $links = $this->commentLinkBuilder->buildCommentedEntityFieldLinks($field_name, $items, $this->getSettings()); + if ($links) { + $links = array('comment__' . $field_name => $links); + } $elements[] = $output + array( '#comment_type' => $this->getFieldSetting('comment_type'), '#comment_display_mode' => $this->getSetting('default_mode'), 'comments' => array(), 'comment_form' => array(), - 'links' => $this->buildLinks($items), + 'links' => $links, ); } @@ -333,156 +349,4 @@ public function settingsSummary() { return array($this->t('Showing @per_page @mode comments with @form and @links', $variables)); } - /** - * Builds links for commented entity. - */ - protected function buildLinks(FieldItemListInterface $items) { - $links = array(); - if ($this->getSetting('show_links') == static::LINKS_NONE) { - return $links; - } - - $field_name = $this->fieldDefinition->getName(); - $entity = $items->getEntity(); - $commenting_status = $items->status; - if ($commenting_status != CommentItemInterface::HIDDEN) { - // Entity has commenting status open or closed. - $link_style = $this->getSetting('show_links'); - if ($link_style == static::LINKS_RSS) { - // Add a comments RSS element which is a URL to the comments of this - // entity. - $options = array( - 'fragment' => 'comments', - 'absolute' => TRUE, - ); - $entity->rss_elements[] = array( - 'key' => 'comments', - 'value' => $entity->url('canonical', $options), - ); - } - elseif ($link_style == static::LINKS_TEASER) { - // Teaser style links: display the number of comments that have been posted, - // or a link to add new comments if the user has permission, the entity - // is open to new comments, and there currently are none. - if ($this->currentUser->hasPermission('access comments')) { - if (!empty($items->comment_count)) { - $links['comment-comments'] = array( - 'title' => $this->formatPlural($items->comment_count, '1 comment', '@count comments'), - 'attributes' => array('title' => $this->t('Jump to the first comment of this posting.')), - 'fragment' => 'comments', - ) + $entity->urlInfo()->toArray(); - if ($this->moduleHandler->moduleExists('history')) { - $links['comment-new-comments'] = array( - 'title' => '', - 'href' => '', - 'attributes' => array( - 'class' => 'hidden', - 'title' => t('Jump to the first new comment of this posting.'), - 'data-history-node-last-comment-timestamp' => $items->last_comment_timestamp, - 'data-history-node-field-name' => $field_name, - 'data-comment-per-page' => $this->getSetting('per_page'), - 'data-comment-default-mode' => $this->getSetting('default_mode'), - ), - ); - } - } - } - // Provide a link to new comment form. - if ($commenting_status == CommentItemInterface::OPEN) { - $comment_form_location = $this->getSetting('form_location'); - if ($this->currentUser->hasPermission('post comments')) { - $links['comment-add'] = array( - 'title' => t('Add new comment'), - 'language' => $entity->language(), - 'attributes' => array('title' => t('Add a new comment to this page.')), - 'fragment' => 'comment-form', - ); - if ($comment_form_location == CommentItemInterface::FORM_SEPARATE_PAGE) { - $links['comment-add']['route_name'] = 'comment.reply'; - $links['comment-add']['route_parameters'] = array( - 'entity_type' => $entity->getEntityTypeId(), - 'entity_id' => $entity->id(), - 'field_name' => $field_name, - ); - } - else { - $links['comment-add'] += $entity->urlInfo()->toArray(); - } - } - elseif ($this->currentUser->isAnonymous()) { - $links['comment-forbidden'] = array( - 'title' => $this->commentManager->forbiddenMessage($entity, $field_name), - 'html' => TRUE, - ); - } - } - } - else { - // Default links: add a "post comment" link if the user is allowed to - // post comments and if this node is allowing new comments. - if ($commenting_status == CommentItemInterface::OPEN) { - $comment_form_location = $this->getSetting('form_location'); - if ($this->currentUser->hasPermission('post comments')) { - // Show the "post comment" link if the form is on another page, or - // if there are existing comments that the link will skip past. - if ($comment_form_location == CommentItemInterface::FORM_SEPARATE_PAGE || (!empty($items->comment_count) && $this->currentUser->hasPermission('access comments'))) { - $links['comment-add'] = array( - 'title' => t('Add new comment'), - 'attributes' => array('title' => t('Share your thoughts and opinions related to this posting.')), - 'fragment' => 'comment-form', - ); - if ($comment_form_location == CommentItemInterface::FORM_SEPARATE_PAGE) { - $links['comment-add']['route_name'] = 'comment.reply'; - $links['comment-add']['route_parameters'] = array( - 'entity_type' => $entity->getEntityTypeId(), - 'entity_id' => $entity->id(), - 'field_name' => $field_name, - ); - } - else { - $links['comment-add'] += $entity->urlInfo()->toArray(); - } - } - } - elseif ($this->currentUser->isAnonymous()) { - $links['comment-forbidden'] = array( - 'title' => $this->commentManager->forbiddenMessage($entity, $field_name), - 'html' => TRUE, - ); - } - } - } - - if (!empty($links)) { - $build['comment__' . $field_name] = array( - '#theme' => 'links__entity__comment__' . $field_name, - '#links' => $links, - '#attributes' => array('class' => array('links', 'inline')), - ); - if ($link_style == static::LINKS_TEASER && $this->moduleHandler->moduleExists('history') && $this->currentUser->isAuthenticated() - // @todo revisit this condition when history.module is generalized; - // see https://www.drupal.org/node/2081585. - && $entity->getEntityTypeId() == 'node') { - $build['comment__' . $field_name]['#attached']['library'][] = 'comment/drupal.node-new-comments-link'; - - // Embed the metadata for the "X new comments" link (if any) on this - // node. - $build['comment__' . $field_name]['#post_render_cache']['history_attach_timestamp'] = array( - array($entity->getEntityTypeId() . '_id' => $entity->id()), - ); - $build['comment__' . $field_name]['#post_render_cache']['Drupal\comment\CommentViewBuilder::attachNewCommentsLinkMetadata'] = array( - array( - 'entity_type' => $entity->getEntityTypeId(), - 'entity_id' => $entity->id(), - 'field_name' => $field_name, - 'per_page' => $this->getSetting('per_page'), - 'default_mode' => $this->getSetting('default_mode'), - ), - ); - } - return $build; - } - } - } - } diff --git a/core/modules/comment/tests/src/Unit/CommentLinkBuilderTest.php b/core/modules/comment/tests/src/Unit/CommentLinkBuilderTest.php index 92b56ed..8989bae 100644 --- a/core/modules/comment/tests/src/Unit/CommentLinkBuilderTest.php +++ b/core/modules/comment/tests/src/Unit/CommentLinkBuilderTest.php @@ -9,6 +9,7 @@ use Drupal\comment\CommentLinkBuilder; use Drupal\comment\CommentManagerInterface; +use Drupal\comment\Plugin\Field\FieldFormatter\CommentDefaultFormatter; use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface; use Drupal\node\NodeInterface; use Drupal\simpletest\TestBase; @@ -42,6 +43,14 @@ class CommentLinkBuilderTest extends UnitTestCase { protected $entityViewDisplay; /** + * Field item list(value) mock. + * + * @var \Drupal\Core\Entity\Display\EntityViewDisplayInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $fieldItem; + + + /** * Comment manager mock. * * @var \Drupal\comment\CommentManagerInterface|\PHPUnit_Framework_MockObject_MockObject @@ -88,6 +97,7 @@ protected function setUp() { $this->entityManager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface'); $this->entityStorage = $this->getMock('\Drupal\Core\Entity\EntityStorageInterface'); $this->entityViewDisplay = $this->getMock('Drupal\Core\Entity\Display\EntityViewDisplayInterface'); + $this->fieldItem = $this->getMock('\Drupal\Core\Field\FieldItemListInterface'); $this->commentManager = $this->getMock('\Drupal\comment\CommentManagerInterface'); $this->stringTranslation = $this->getStringTranslationStub(); $this->moduleHandler = $this->getMock('\Drupal\Core\Extension\ModuleHandlerInterface'); @@ -128,6 +138,12 @@ protected function setUp() { * TRUE if the user is anonymous. * @param int $form_location * One of CommentItemInterface::FORM_BELOW|FORM_SEPARATE_PAGE + * @param int $link_style + * CommentDefaultFormatter::LINKS_NONE|LINKS_PAGE|LINKS_RSS|LINKS_TEASER + * @param int $comment_status + * One of CommentItemInterface::OPEN|HIDDEN|CLOSED + * @param int $comment_count + * Number of comments against the field. * @param array $expected * Array of expected links keyed by link ID. Can be either string (link * title) or array of link properties. @@ -136,7 +152,7 @@ protected function setUp() { * * @covers ::buildCommentedEntityLinks() */ - public function testCommentLinkBuilder(NodeInterface $node, $context, $has_access_comments, $history_exists, $has_post_comments, $is_anonymous, $form_location, $expected) { + public function testCommentLinkBuilder(NodeInterface $node, $context, $has_access_comments, $history_exists, $has_post_comments, $is_anonymous, $form_location, $link_style, $comment_status, $comment_count, $expected) { $this->moduleHandler->expects($this->any()) ->method('moduleExists') ->with('history') @@ -153,19 +169,40 @@ public function testCommentLinkBuilder(NodeInterface $node, $context, $has_acces $this->currentUser->expects($this->any()) ->method('isAnonymous') ->willReturn($is_anonymous); + $this->entityStorage->expects($this->any()) ->method('load') - ->with($node->getEntityTypeId() . '.' . $node->bundle() . '.' . $context['view_mode']) + ->with($node->getEntityTypeId() . '.' . $node->bundle() . '.teaser') ->willReturn($this->entityViewDisplay); $this->entityViewDisplay->expects($this->any()) ->method('getComponent') ->willReturn(array('settings' => array( 'form_location' => $form_location, + 'show_links' => $link_style, // These settings influence the page argument to the 'new comments' url, // which we're not testing, so return static values. 'default_mode' => CommentManagerInterface::COMMENT_MODE_THREADED, 'per_page' => 50 ))); + + if (empty($this->timestamp)) { + $this->timestamp = time(); + } + $this->fieldItem->expects($this->any()) + ->method('getEntity') + ->willReturn($node); + $this->fieldItem->expects($this->any()) + ->method('__get') + ->will($this->returnValueMap(array( + array('status', $comment_status), + array('comment_count', $comment_count), + array('last_comment_timestamp', $this->timestamp), + ))); + $node->expects($this->any()) + ->method('get') + ->with('comment') + ->willReturn($this->fieldItem); + $links = $this->commentLinkBuilder->buildCommentedEntityLinks($node, $context); if (!empty($expected)) { if (!empty($links)) { @@ -189,14 +226,12 @@ public function testCommentLinkBuilder(NodeInterface $node, $context, $has_acces else { $this->assertSame($links, $expected); } - if ($context['view_mode'] == 'rss' && $node->get('comment')->status) { + if ($link_style == CommentDefaultFormatter::LINKS_RSS && $node->get('comment')->status) { $found = FALSE; - if ($node->get('comment')->status) { - foreach ($node->rss_elements as $element) { - if ($element['key'] == 'comments') { - $found = TRUE; - break; - } + foreach ($node->rss_elements as $element) { + if ($element['key'] == 'comments') { + $found = TRUE; + break; } } $this->assertTrue($found); @@ -210,25 +245,33 @@ public function getLinkCombinations() { $cases = array(); // No links should be created if the entity doesn't have the field. $cases[] = array( - $this->getMockNode(FALSE, CommentItemInterface::OPEN, 1), + $this->getMockNode(FALSE), array('view_mode' => 'teaser'), TRUE, TRUE, TRUE, TRUE, CommentItemInterface::FORM_BELOW, + CommentDefaultFormatter::LINKS_TEASER, + CommentItemInterface::OPEN, + 1, array(), ); foreach (array('search_result', 'search_index', 'print') as $view_mode) { // Nothing should be output in these view modes. + // (Other view modes do not influence link display; they're only used for + // loading display settings. So we arbitrarily use 'teaser'.) $cases[] = array( - $this->getMockNode(TRUE, CommentItemInterface::OPEN, 1), + $this->getMockNode(TRUE), array('view_mode' => $view_mode), TRUE, TRUE, TRUE, TRUE, CommentItemInterface::FORM_BELOW, + CommentDefaultFormatter::LINKS_TEASER, + CommentItemInterface::OPEN, + 1, array(), ); } @@ -245,25 +288,34 @@ public function getLinkCombinations() { CommentItemInterface::CLOSED, CommentItemInterface::HIDDEN, ), - 'view_mode' => array( - 'teaser', 'rss', 'full', + 'link_style' => array( + CommentDefaultFormatter::LINKS_NONE, + CommentDefaultFormatter::LINKS_PAGE, + CommentDefaultFormatter::LINKS_RSS, + CommentDefaultFormatter::LINKS_TEASER, ), ); $permutations = TestBase::generatePermutations($combinations); foreach ($permutations as $combination) { $case = array( - $this->getMockNode(TRUE, $combination['comments'], $combination['comment_count']), - array('view_mode' => $combination['view_mode']), + $this->getMockNode(TRUE), + array('view_mode' => 'teaser'), $combination['has_access_comments'], $combination['history_exists'], $combination['has_post_comments'], $combination['is_anonymous'], $combination['form_location'], + $combination['link_style'], + $combination['comments'], + $combination['comment_count'], ); $expected = array(); - // When comments are enabled in teaser mode, and comments exist, and the - // user has access - we can output the comment count. - if ($combination['comments'] && $combination['view_mode'] == 'teaser' && $combination['comment_count'] && $combination['has_access_comments']) { + // When comments are enabled with teaser links, and comments exist, and + // the user has access - we can output the comment count. + if ($combination['comments'] != CommentItemInterface::HIDDEN + && $combination['link_style'] == CommentDefaultFormatter::LINKS_TEASER + && $combination['comment_count'] + && $combination['has_access_comments']) { $expected['comment-comments'] = '1 comment'; // And if history module exists, we can show a 'new comments' link. if ($combination['history_exists']) { @@ -271,14 +323,16 @@ public function getLinkCombinations() { } } // All view modes other than RSS. - if ($combination['view_mode'] != 'rss') { + if ($combination['link_style'] != CommentDefaultFormatter::LINKS_RSS) { // Where commenting is open. if ($combination['comments'] == CommentItemInterface::OPEN) { // And the user has post-comments permission. if ($combination['has_post_comments']) { - // If the view mode is teaser, or the user can access comments and + // If the link style is teaser, or the user can access comments and // comments exist or the form is on a separate page. - if ($combination['view_mode'] == 'teaser' || ($combination['has_access_comments'] && $combination['comment_count']) || $combination['form_location'] == CommentItemInterface::FORM_SEPARATE_PAGE) { + if ($combination['link_style'] == CommentDefaultFormatter::LINKS_TEASER + || ($combination['has_access_comments'] && $combination['comment_count']) + || $combination['form_location'] == CommentItemInterface::FORM_SEPARATE_PAGE) { // There should be a add comment link. $expected['comment-add'] = array('title' => 'Add new comment'); if ($combination['form_location'] == CommentItemInterface::FORM_BELOW) { @@ -310,33 +364,16 @@ public function getLinkCombinations() { * * @param bool $has_field * TRUE if the node has the 'comment' field. - * @param int $comment_status - * One of CommentItemInterface::OPEN|HIDDEN|CLOSED - * @param int $comment_count - * Number of comments against the field. * * @return \Drupal\node\NodeInterface|\PHPUnit_Framework_MockObject_MockObject * Mock node for testing. */ - protected function getMockNode($has_field, $comment_status, $comment_count) { + protected function getMockNode($has_field) { $node = $this->getMock('\Drupal\node\NodeInterface'); $node->expects($this->once()) ->method('hasField') ->willReturn($has_field); - if (empty($this->timestamp)) { - $this->timestamp = time(); - } - $field_item = (object) array( - 'status' => $comment_status, - 'comment_count' => $comment_count, - 'last_comment_timestamp' => $this->timestamp, - ); - $node->expects($this->any()) - ->method('get') - ->with('comment') - ->willReturn($field_item); - $field_definition = $this->getMock('\Drupal\Core\Field\FieldDefinitionInterface'); $node->expects($this->any()) ->method('getFieldDefinition')