NodeNewComments.php

Same filename in other branches
  1. 9 core/modules/comment/src/Plugin/views/field/NodeNewComments.php
  2. 10 core/modules/comment/src/Plugin/views/field/NodeNewComments.php
  3. 11.x core/modules/comment/src/Plugin/views/field/NodeNewComments.php

Namespace

Drupal\comment\Plugin\views\field

File

core/modules/comment/src/Plugin/views/field/NodeNewComments.php

View source
<?php

namespace Drupal\comment\Plugin\views\field;

use Drupal\Core\Database\Connection;
use Drupal\comment\CommentInterface;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\node\Entity\Node;
use Drupal\views\Plugin\views\field\NumericField;
use Drupal\views\Plugin\views\display\DisplayPluginBase;
use Drupal\views\ResultRow;
use Drupal\views\ViewExecutable;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Field handler to display the number of new comments.
 *
 * @ingroup views_field_handlers
 *
 * @ViewsField("node_new_comments")
 */
class NodeNewComments extends NumericField {
    
    /**
     * {@inheritdoc}
     */
    public function usesGroupBy() {
        return FALSE;
    }
    
    /**
     * Database Service Object.
     *
     * @var \Drupal\Core\Database\Connection
     */
    protected $database;
    
    /**
     * The entity type manager.
     *
     * @var \Drupal\Core\Entity\EntityTypeManagerInterface
     */
    protected $entityTypeManager;
    
    /**
     * The entity field manager.
     *
     * @var \Drupal\Core\Entity\EntityFieldManagerInterface
     */
    protected $entityFieldManager;
    
    /**
     * Constructs a \Drupal\comment\Plugin\views\field\NodeNewComments object.
     *
     * @param array $configuration
     *   A configuration array containing information about the plugin instance.
     * @param string $plugin_id
     *   The plugin_id for the plugin instance.
     * @param mixed $plugin_definition
     *   The plugin implementation definition.
     * @param \Drupal\Core\Database\Connection $database
     *   Database Service Object.
     * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
     *   The entity type manager service.
     * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager
     *   The entity field manager service.
     */
    public function __construct(array $configuration, $plugin_id, $plugin_definition, Connection $database, EntityTypeManagerInterface $entity_type_manager = NULL, EntityFieldManagerInterface $entity_field_manager = NULL) {
        parent::__construct($configuration, $plugin_id, $plugin_definition);
        $this->database = $database;
        if (!$entity_type_manager) {
            @trigger_error("Not passing the entity type manager to the NodeNewComments constructor is deprecated in drupal:8.8.0 and will be required in drupal:9.0.0. @see https://www.drupal.org/node/3047897", E_USER_DEPRECATED);
            $entity_type_manager = \Drupal::entityTypeManager();
        }
        if (!$entity_field_manager) {
            @trigger_error("Not passing the entity type manager to the NodeNewComments constructor is deprecated in drupal:8.8.0 and will be required in drupal:9.0.0. @see https://www.drupal.org/node/3047897", E_USER_DEPRECATED);
            $entity_field_manager = \Drupal::service('entity_field.manager');
        }
        $this->entityTypeManager = $entity_type_manager;
        $this->entityFieldManager = $entity_field_manager;
    }
    
    /**
     * {@inheritdoc}
     */
    public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
        return new static($configuration, $plugin_id, $plugin_definition, $container->get('database'), $container->get('entity_type.manager'), $container->get('entity_field.manager'));
    }
    
    /**
     * {@inheritdoc}
     */
    public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
        parent::init($view, $display, $options);
        $this->additional_fields['entity_id'] = 'nid';
        $this->additional_fields['type'] = 'type';
        $this->additional_fields['comment_count'] = [
            'table' => 'comment_entity_statistics',
            'field' => 'comment_count',
        ];
    }
    
    /**
     * {@inheritdoc}
     */
    protected function defineOptions() {
        $options = parent::defineOptions();
        $options['link_to_comment'] = [
            'default' => TRUE,
        ];
        return $options;
    }
    
    /**
     * {@inheritdoc}
     */
    public function buildOptionsForm(&$form, FormStateInterface $form_state) {
        $form['link_to_comment'] = [
            '#title' => $this->t('Link this field to new comments'),
            '#description' => $this->t("Enable to override this field's links."),
            '#type' => 'checkbox',
            '#default_value' => $this->options['link_to_comment'],
        ];
        parent::buildOptionsForm($form, $form_state);
    }
    
    /**
     * {@inheritdoc}
     */
    public function query() {
        $this->ensureMyTable();
        $this->addAdditionalFields();
        $this->field_alias = $this->table . '_' . $this->field;
    }
    
    /**
     * {@inheritdoc}
     */
    public function preRender(&$values) {
        $user = \Drupal::currentUser();
        if ($user->isAnonymous() || empty($values)) {
            return;
        }
        $nids = [];
        $ids = [];
        foreach ($values as $id => $result) {
            $nids[] = $result->{$this->aliases['nid']};
            $values[$id]->{$this->field_alias} = 0;
            // Create a reference so we can find this record in the values again.
            if (empty($ids[$result->{$this->aliases['nid']}])) {
                $ids[$result->{$this->aliases['nid']}] = [];
            }
            $ids[$result->{$this->aliases['nid']}][] = $id;
        }
        if ($nids) {
            $result = $this->database
                ->query("SELECT n.nid, COUNT(c.cid) AS num_comments FROM {node} n INNER JOIN {comment_field_data} c ON n.nid = c.entity_id AND c.entity_type = 'node' AND c.default_langcode = 1\n        LEFT JOIN {history} h ON h.nid = n.nid AND h.uid = :h_uid WHERE n.nid IN ( :nids[] )\n        AND c.changed > GREATEST(COALESCE(h.timestamp, :timestamp1), :timestamp2) AND c.status = :status GROUP BY n.nid", [
                ':status' => CommentInterface::PUBLISHED,
                ':h_uid' => $user->id(),
                ':nids[]' => $nids,
                ':timestamp1' => HISTORY_READ_LIMIT,
                ':timestamp2' => HISTORY_READ_LIMIT,
            ]);
            foreach ($result as $node) {
                foreach ($ids[$node->nid] as $id) {
                    $values[$id]->{$this->field_alias} = $node->num_comments;
                }
            }
        }
    }
    
    /**
     * Prepares the link to the first new comment.
     *
     * @param string $data
     *   The XSS safe string for the link text.
     * @param \Drupal\views\ResultRow $values
     *   The values retrieved from a single row of a view's query result.
     *
     * @return string
     *   Returns a string for the link text.
     */
    protected function renderLink($data, ResultRow $values) {
        if (!empty($this->options['link_to_comment']) && $data !== NULL && $data !== '') {
            $node_type = $this->getValue($values, 'type');
            $node = Node::create([
                'nid' => $this->getValue($values, 'nid'),
                'type' => $node_type,
            ]);
            // Because there is no support for selecting a specific comment field to
            // reference, we arbitrarily use the first such field name we find.
            // @todo Provide a means for selecting the comment field.
            //   https://www.drupal.org/node/2594201
            $field_map = $this->entityFieldManager
                ->getFieldMapByFieldType('comment');
            $comment_field_name = 'comment';
            foreach ($field_map['node'] as $field_name => $field_data) {
                foreach ($field_data['bundles'] as $bundle_name) {
                    if ($node_type == $bundle_name) {
                        $comment_field_name = $field_name;
                        break 2;
                    }
                }
            }
            $page_number = $this->entityTypeManager
                ->getStorage('comment')
                ->getNewCommentPageNumber($this->getValue($values, 'comment_count'), $this->getValue($values), $node, $comment_field_name);
            $this->options['alter']['make_link'] = TRUE;
            $this->options['alter']['url'] = $node->toUrl();
            $this->options['alter']['query'] = $page_number ? [
                'page' => $page_number,
            ] : NULL;
            $this->options['alter']['fragment'] = 'new';
        }
        return $data;
    }
    
    /**
     * {@inheritdoc}
     */
    public function render(ResultRow $values) {
        $value = $this->getValue($values);
        if (!empty($value)) {
            return $this->renderLink(parent::render($values), $values);
        }
        else {
            $this->options['alter']['make_link'] = FALSE;
        }
    }

}

Classes

Title Deprecated Summary
NodeNewComments Field handler to display the number of new comments.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.