diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index db68f43cd8..45fe53901a 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -216,6 +216,117 @@ function comment_entity_view(array &$build, EntityInterface $entity, EntityViewD
'value' => $entity->toUrl('canonical', $options)->toString(),
];
}
+ 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 node
+ // is open to new comments, and there currently are none.
+ if (user_access('access comments')) {
+ if (!empty($entity->get($field_name)->comment_count)) {
+ $links['comment-comments'] = array(
+ 'title' => format_plural($entity->get($field_name)->comment_count, '1 comment', '@count comments'),
+ 'attributes' => array('title' => t('Jump to the first comment of this posting.')),
+ 'fragment' => 'comments',
+ 'html' => TRUE,
+ ) + $entity->urlInfo()->toArray();
+ if (\Drupal::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' => $entity->get($field_name)->last_comment_timestamp,
+ 'data-history-node-field-name' => $field_name,
+ ),
+ 'html' => TRUE,
+ );
+ }
+ }
+ }
+ // Provide a link to new comment form.
+ if ($commenting_status == CommentItemInterface::OPEN) {
+ $comment_form_location = $field_definition->getSetting('form_location');
+ if (user_access('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 == COMMENT_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 (\Drupal::currentUser()->isAnonymous()) {
+ $links['comment-forbidden'] = array(
+ 'title' => \Drupal::service('comment.helper')->forbiddenMessage($entity, $field_name),
+ 'html' => TRUE,
+ );
+ }
+ }
+ }
+ else {
+ // Node in other view modes: 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 = $field_definition->getSetting('form_location');
+ if (user_access('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 == COMMENT_FORM_SEPARATE_PAGE || (!empty($entity->get($field_name)->comment_count) && user_access('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 == COMMENT_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 (\Drupal::currentUser()->isAnonymous()) {
+ $links['comment-forbidden'] = array(
+ 'title' => \Drupal::service('comment.helper')->forbiddenMessage($entity, $field_name),
+ 'html' => TRUE,
+ );
+ }
+ }
+ }
+ }
+
+ if (!empty($links)) {
+ $node_links['comment__' . $field_name] = array(
+ '#theme' => 'links__entity__comment__' . $field_name,
+ '#links' => $links,
+ '#attributes' => array('class' => array('links', 'inline')),
+ );
+ if ($view_mode == 'teaser' && \Drupal::moduleHandler()->moduleExists('history') && \Drupal::currentUser()->isAuthenticated()) {
+ $node_links['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.
+ $node_links['comment__' . $field_name]['#post_render_cache']['history_attach_timestamp'] = array(
+ array('node_id' => $entity->id()),
+ );
+ $node_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),
+ );
+ }
}
}
}
diff --git a/core/modules/comment/comment.services.yml b/core/modules/comment/comment.services.yml
index 3595854ceb..7fb1911046 100644
--- a/core/modules/comment/comment.services.yml
+++ b/core/modules/comment/comment.services.yml
@@ -7,7 +7,11 @@ services:
comment.manager:
class: Drupal\comment\CommentManager
- arguments: ['@entity_type.manager', '@config.factory', '@string_translation', '@module_handler', '@current_user', '@entity_field.manager', '@entity_display.repository']
+ arguments: ['@entity_type.manager', '@module_handler', '@current_user', '@entity_field.manager', '@entity_display.repository']
+
+ comment.helper:
+ class: Drupal\comment\CommentHelper
+ arguments: ['@entity.manager', '@config.factory', '@string_translation', '@url_generator']
comment.statistics:
class: Drupal\comment\CommentStatistics
diff --git a/core/modules/comment/src/CommentHelper.php b/core/modules/comment/src/CommentHelper.php
new file mode 100644
index 0000000000..a7845e58d9
--- /dev/null
+++ b/core/modules/comment/src/CommentHelper.php
@@ -0,0 +1,124 @@
+entityManager = $entity_manager;
+ $this->userConfig = $config_factory->get('user.settings');
+ $this->translationManager = $translation_manager;
+ $this->urlGenerator = $url_generator;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function forbiddenMessage(EntityInterface $entity, $field_name) {
+ if (!isset($this->authenticatedCanPostComments)) {
+ // We only output a link if we are certain that users will get the
+ // permission to post comments by logging in.
+ $this->authenticatedCanPostComments = $this->entityManager
+ ->getStorage('user_role')
+ ->load(DRUPAL_AUTHENTICATED_RID)
+ ->hasPermission('post comments');
+ }
+
+ if ($this->authenticatedCanPostComments) {
+ // We cannot use drupal_get_destination() because these links
+ // sometimes appear on /node and taxonomy listing pages.
+ if ($entity->get($field_name)->getFieldDefinition()->getSetting('form_location') == COMMENT_FORM_SEPARATE_PAGE) {
+ $destination = array('destination' => 'comment/reply/' . $entity->getEntityTypeId() . '/' . $entity->id() . '/' . $field_name . '#comment-form');
+ }
+ else {
+ $destination = array('destination' => $entity->getSystemPath() . '#comment-form');
+ }
+
+ if ($this->userConfig->get('register') != USER_REGISTER_ADMINISTRATORS_ONLY) {
+ // Users can register themselves.
+ return $this->t('Log in or register to post comments', array(
+ '@login' => $this->urlGenerator->generateFromRoute('user.login', array(), array('query' => $destination)),
+ '@register' => $this->urlGenerator->generateFromRoute('user.register', array(), array('query' => $destination)),
+ ));
+ }
+ else {
+ // Only admins can add new users, no public registration.
+ return $this->t('Log in to post comments', array(
+ '@login' => $this->urlGenerator->generateFromRoute('user.login', array(), array('query' => $destination)),
+ ));
+ }
+ }
+ return '';
+ }
+
+ /**
+ * Translates a string to the current language or to a given language.
+ *
+ * See the t() documentation for details.
+ */
+ protected function t($string, array $args = array(), array $options = array()) {
+ return $this->translationManager->translate($string, $args, $options);
+ }
+
+}
diff --git a/core/modules/comment/src/CommentHelperInterface.php b/core/modules/comment/src/CommentHelperInterface.php
new file mode 100644
index 0000000000..dd2d282323
--- /dev/null
+++ b/core/modules/comment/src/CommentHelperInterface.php
@@ -0,0 +1,34 @@
+entityTypeManager = $entity_type_manager;
- $this->userConfig = $config_factory->get('user.settings');
$this->stringTranslation = $string_translation;
$this->moduleHandler = $module_handler;
$this->currentUser = $current_user;
@@ -147,51 +128,6 @@ public function addBodyField($comment_type_id) {
}
}
- /**
- * {@inheritdoc}
- */
- public function forbiddenMessage(EntityInterface $entity, $field_name) {
- if (!isset($this->authenticatedCanPostComments)) {
- // We only output a link if we are certain that users will get the
- // permission to post comments by logging in.
- $this->authenticatedCanPostComments = $this->entityTypeManager
- ->getStorage('user_role')
- ->load(RoleInterface::AUTHENTICATED_ID)
- ->hasPermission('post comments');
- }
-
- if ($this->authenticatedCanPostComments) {
- // We cannot use the redirect.destination service here because these links
- // sometimes appear on /node and taxonomy listing pages.
- if ($entity->get($field_name)->getFieldDefinition()->getSetting('form_location') == CommentItemInterface::FORM_SEPARATE_PAGE) {
- $comment_reply_parameters = [
- 'entity_type' => $entity->getEntityTypeId(),
- 'entity' => $entity->id(),
- 'field_name' => $field_name,
- ];
- $destination = ['destination' => Url::fromRoute('comment.reply', $comment_reply_parameters, ['fragment' => 'comment-form'])->toString()];
- }
- else {
- $destination = ['destination' => $entity->toUrl('canonical', ['fragment' => 'comment-form'])->toString()];
- }
-
- if ($this->userConfig->get('register') != UserInterface::REGISTER_ADMINISTRATORS_ONLY) {
- // Users can register themselves.
- return $this->t('Log in or register to post comments', [
- ':login' => Url::fromRoute('user.login', [], ['query' => $destination])->toString(),
- ':register' => Url::fromRoute('user.register', [], ['query' => $destination])->toString(),
- ]);
- }
- else {
- // Only admins can add new users, no public registration.
- return $this->t('Log in to post comments', [
- ':login' => Url::fromRoute('user.login', [], ['query' => $destination])->toString(),
- ]);
- }
- }
- return '';
- }
-
/**
* {@inheritdoc}
*/
@@ -234,4 +170,11 @@ public function getCountNewComments(EntityInterface $entity, $field_name = NULL,
return FALSE;
}
+ public function getFieldUIPageTitle($commented_entity_type, $field_name) {
+ $field_info = $this->getFields($commented_entity_type);
+ $sample_bundle = reset($field_info[$field_name]['bundles']);
+ $sample_definition = $this->entityManager->getFieldDefinitions($commented_entity_type, $sample_bundle)[$field_name];
+ return String::checkPlain($sample_definition->getLabel());
+ }
+
}
diff --git a/core/modules/comment/src/CommentViewBuilder.php b/core/modules/comment/src/CommentViewBuilder.php
index b3fd17e59c..7d40b89075 100644
--- a/core/modules/comment/src/CommentViewBuilder.php
+++ b/core/modules/comment/src/CommentViewBuilder.php
@@ -180,6 +180,107 @@ public function buildComponents(array &$build, array $entities, array $displays,
}
}
+ /**
+ * #post_render_cache callback; replaces the placeholder with comment links.
+ *
+ * Renders the links on a comment.
+ *
+ * @param array $element
+ * The renderable array that contains the to be replaced placeholder.
+ * @param array $context
+ * An array with the following keys:
+ * - comment_entity_id: a comment entity ID
+ * - view_mode: the view mode in which the comment entity is being viewed
+ * - langcode: in which language the comment entity is being viewed
+ * - commented_entity_type: the entity type to which the comment is attached
+ * - commented_entity_id: the entity ID to which the comment is attached
+ * - in_preview: whether the comment is currently being previewed
+ *
+ * @return array
+ * A renderable array representing the comment links.
+ */
+ public static function renderLinks(array $element, array $context) {
+ $callback = '\Drupal\comment\CommentViewBuilder::renderLinks';
+ $placeholder = drupal_render_cache_generate_placeholder($callback, $context, $context['token']);
+ $links = array(
+ '#theme' => 'links__comment',
+ '#pre_render' => array('drupal_pre_render_links'),
+ '#attributes' => array('class' => array('links', 'inline')),
+ );
+
+ if (!$context['in_preview']) {
+ $entity = entity_load('comment', $context['comment_entity_id']);
+ $commented_entity = entity_load($context['commented_entity_type'], $context['commented_entity_id']);
+
+ $links['comment'] = self::buildLinks($entity, $commented_entity);
+
+ // Allow other modules to alter the comment links.
+ $hook_context = array(
+ 'view_mode' => $context['view_mode'],
+ 'langcode' => $context['langcode'],
+ 'commented_entity' => $commented_entity
+ );
+ \Drupal::moduleHandler()->alter('comment_links', $links, $entity, $hook_context);
+ }
+ $markup = drupal_render($links);
+ $element['#markup'] = str_replace($placeholder, $markup, $element['#markup']);
+
+ return $element;
+ }
+
+ /**
+ * Build the default links (reply, edit, delete …) for a comment.
+ *
+ * @param \Drupal\comment\CommentInterface $entity
+ * The comment object.
+ * @param \Drupal\Core\Entity\EntityInterface $commented_entity
+ * The entity to which the comment is attached.
+ *
+ * @return array
+ * An array that can be processed by drupal_pre_render_links().
+ */
+ protected static function buildLinks(CommentInterface $entity, EntityInterface $commented_entity) {
+ $links = array();
+ $status = $commented_entity->get($entity->getFieldName())->status;
+
+ if ($status == CommentItemInterface::OPEN) {
+ if ($entity->access('delete')) {
+ $links['comment-delete'] = array(
+ 'title' => t('Delete'),
+ 'href' => "comment/{$entity->id()}/delete",
+ 'html' => TRUE,
+ );
+ }
+
+ if ($entity->access('update')) {
+ $links['comment-edit'] = array(
+ 'title' => t('Edit'),
+ 'href' => "comment/{$entity->id()}/edit",
+ 'html' => TRUE,
+ );
+ }
+ if ($entity->access('create')) {
+ $links['comment-reply'] = array(
+ 'title' => t('Reply'),
+ 'href' => "comment/reply/{$entity->getCommentedEntityTypeId()}/{$entity->getCommentedEntityId()}/{$entity->getFieldName()}/{$entity->id()}",
+ 'html' => TRUE,
+ );
+ }
+ if (!$entity->isPublished() && $entity->access('approve')) {
+ $links['comment-approve'] = array(
+ 'title' => t('Approve'),
+ 'route_name' => 'comment.approve',
+ 'route_parameters' => array('comment' => $entity->id()),
+ 'html' => TRUE,
+ );
+ }
+ if (empty($links) && \Drupal::currentUser()->isAnonymous()) {
+ $links['comment-forbidden']['title'] = \Drupal::service('comment.helper')->forbiddenMessage($commented_entity, $entity->getFieldName());
+ $links['comment-forbidden']['html'] = TRUE;
+ }
+ }
+ }
+
/**
* {@inheritdoc}
*/