Updated Drupal to 8.6. This goes with the following updates because it's possible...
[yaffs-website] / web / core / modules / comment / src / Plugin / views / field / NodeNewComments.php
1 <?php
2
3 namespace Drupal\comment\Plugin\views\field;
4
5 use Drupal\Core\Database\Connection;
6 use Drupal\comment\CommentInterface;
7 use Drupal\Core\Form\FormStateInterface;
8 use Drupal\node\Entity\Node;
9 use Drupal\views\Plugin\views\field\NumericField;
10 use Drupal\views\Plugin\views\display\DisplayPluginBase;
11 use Drupal\views\ResultRow;
12 use Drupal\views\ViewExecutable;
13 use Symfony\Component\DependencyInjection\ContainerInterface;
14
15 /**
16  * Field handler to display the number of new comments.
17  *
18  * @ingroup views_field_handlers
19  *
20  * @ViewsField("node_new_comments")
21  */
22 class NodeNewComments extends NumericField {
23
24   /**
25    * {@inheritdoc}
26    */
27   public function usesGroupBy() {
28     return FALSE;
29   }
30
31   /**
32    * Database Service Object.
33    *
34    * @var \Drupal\Core\Database\Connection
35    */
36   protected $database;
37
38   /**
39    * Constructs a \Drupal\comment\Plugin\views\field\NodeNewComments object.
40    *
41    * @param array $configuration
42    *   A configuration array containing information about the plugin instance.
43    * @param string $plugin_id
44    *   The plugin_id for the plugin instance.
45    * @param mixed $plugin_definition
46    *   The plugin implementation definition.
47    * @param \Drupal\Core\Database\Connection $database
48    *   Database Service Object.
49    */
50   public function __construct(array $configuration, $plugin_id, $plugin_definition, Connection $database) {
51     parent::__construct($configuration, $plugin_id, $plugin_definition);
52
53     $this->database = $database;
54   }
55
56   /**
57    * {@inheritdoc}
58    */
59   public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
60     return new static($configuration, $plugin_id, $plugin_definition, $container->get('database'));
61   }
62
63   /**
64    * {@inheritdoc}
65    */
66   public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
67     parent::init($view, $display, $options);
68
69     $this->additional_fields['entity_id'] = 'nid';
70     $this->additional_fields['type'] = 'type';
71     $this->additional_fields['comment_count'] = ['table' => 'comment_entity_statistics', 'field' => 'comment_count'];
72   }
73
74   /**
75    * {@inheritdoc}
76    */
77   protected function defineOptions() {
78     $options = parent::defineOptions();
79
80     $options['link_to_comment'] = ['default' => TRUE];
81
82     return $options;
83   }
84
85   /**
86    * {@inheritdoc}
87    */
88   public function buildOptionsForm(&$form, FormStateInterface $form_state) {
89     $form['link_to_comment'] = [
90       '#title' => $this->t('Link this field to new comments'),
91       '#description' => $this->t("Enable to override this field's links."),
92       '#type' => 'checkbox',
93       '#default_value' => $this->options['link_to_comment'],
94     ];
95
96     parent::buildOptionsForm($form, $form_state);
97   }
98
99   /**
100    * {@inheritdoc}
101    */
102   public function query() {
103     $this->ensureMyTable();
104     $this->addAdditionalFields();
105     $this->field_alias = $this->table . '_' . $this->field;
106   }
107
108   /**
109    * {@inheritdoc}
110    */
111   public function preRender(&$values) {
112     $user = \Drupal::currentUser();
113     if ($user->isAnonymous() || empty($values)) {
114       return;
115     }
116
117     $nids = [];
118     $ids = [];
119     foreach ($values as $id => $result) {
120       $nids[] = $result->{$this->aliases['nid']};
121       $values[$id]->{$this->field_alias} = 0;
122       // Create a reference so we can find this record in the values again.
123       if (empty($ids[$result->{$this->aliases['nid']}])) {
124         $ids[$result->{$this->aliases['nid']}] = [];
125       }
126       $ids[$result->{$this->aliases['nid']}][] = $id;
127     }
128
129     if ($nids) {
130       $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
131         LEFT JOIN {history} h ON h.nid = n.nid AND h.uid = :h_uid WHERE n.nid IN ( :nids[] )
132         AND c.changed > GREATEST(COALESCE(h.timestamp, :timestamp1), :timestamp2) AND c.status = :status GROUP BY n.nid", [
133         ':status' => CommentInterface::PUBLISHED,
134         ':h_uid' => $user->id(),
135         ':nids[]' => $nids,
136         ':timestamp1' => HISTORY_READ_LIMIT,
137         ':timestamp2' => HISTORY_READ_LIMIT,
138       ]);
139       foreach ($result as $node) {
140         foreach ($ids[$node->nid] as $id) {
141           $values[$id]->{$this->field_alias} = $node->num_comments;
142         }
143       }
144     }
145   }
146
147   /**
148    * Prepares the link to the first new comment.
149    *
150    * @param string $data
151    *   The XSS safe string for the link text.
152    * @param \Drupal\views\ResultRow $values
153    *   The values retrieved from a single row of a view's query result.
154    *
155    * @return string
156    *   Returns a string for the link text.
157    */
158   protected function renderLink($data, ResultRow $values) {
159     if (!empty($this->options['link_to_comment']) && $data !== NULL && $data !== '') {
160       $node_type = $this->getValue($values, 'type');
161       $node = Node::create([
162         'nid' => $this->getValue($values, 'nid'),
163         'type' => $node_type,
164       ]);
165       // Because there is no support for selecting a specific comment field to
166       // reference, we arbitrarily use the first such field name we find.
167       // @todo Provide a means for selecting the comment field.
168       //   https://www.drupal.org/node/2594201
169       $entity_manager = \Drupal::entityManager();
170       $field_map = $entity_manager->getFieldMapByFieldType('comment');
171       $comment_field_name = 'comment';
172       foreach ($field_map['node'] as $field_name => $field_data) {
173         foreach ($field_data['bundles'] as $bundle_name) {
174           if ($node_type == $bundle_name) {
175             $comment_field_name = $field_name;
176             break 2;
177           }
178         }
179       }
180       $page_number = $entity_manager->getStorage('comment')
181         ->getNewCommentPageNumber($this->getValue($values, 'comment_count'), $this->getValue($values), $node, $comment_field_name);
182       $this->options['alter']['make_link'] = TRUE;
183       $this->options['alter']['url'] = $node->urlInfo();
184       $this->options['alter']['query'] = $page_number ? ['page' => $page_number] : NULL;
185       $this->options['alter']['fragment'] = 'new';
186     }
187
188     return $data;
189   }
190
191   /**
192    * {@inheritdoc}
193    */
194   public function render(ResultRow $values) {
195     $value = $this->getValue($values);
196     if (!empty($value)) {
197       return $this->renderLink(parent::render($values), $values);
198     }
199     else {
200       $this->options['alter']['make_link'] = FALSE;
201     }
202   }
203
204 }