Mercurial > hg > cmmr2012-drupal-site
comparison core/modules/comment/src/CommentStatistics.php @ 0:c75dbcec494b
Initial commit from drush-created site
author | Chris Cannam |
---|---|
date | Thu, 05 Jul 2018 14:24:15 +0000 |
parents | |
children | 12f9dff5fda9 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:c75dbcec494b |
---|---|
1 <?php | |
2 | |
3 namespace Drupal\comment; | |
4 | |
5 use Drupal\Core\Database\Connection; | |
6 use Drupal\Core\Entity\FieldableEntityInterface; | |
7 use Drupal\Core\Entity\EntityChangedInterface; | |
8 use Drupal\Core\Entity\EntityInterface; | |
9 use Drupal\Core\Entity\EntityManagerInterface; | |
10 use Drupal\Core\State\StateInterface; | |
11 use Drupal\Core\Session\AccountInterface; | |
12 use Drupal\user\EntityOwnerInterface; | |
13 | |
14 class CommentStatistics implements CommentStatisticsInterface { | |
15 | |
16 /** | |
17 * The current database connection. | |
18 * | |
19 * @var \Drupal\Core\Database\Connection | |
20 */ | |
21 protected $database; | |
22 | |
23 /** | |
24 * The current logged in user. | |
25 * | |
26 * @var \Drupal\Core\Session\AccountInterface | |
27 */ | |
28 protected $currentUser; | |
29 | |
30 /** | |
31 * The entity manager service. | |
32 * | |
33 * @var \Drupal\Core\Entity\EntityManagerInterface | |
34 */ | |
35 protected $entityManager; | |
36 | |
37 /** | |
38 * The state service. | |
39 * | |
40 * @var \Drupal\Core\State\StateInterface | |
41 */ | |
42 protected $state; | |
43 | |
44 /** | |
45 * Constructs the CommentStatistics service. | |
46 * | |
47 * @param \Drupal\Core\Database\Connection $database | |
48 * The active database connection. | |
49 * @param \Drupal\Core\Session\AccountInterface $current_user | |
50 * The current logged in user. | |
51 * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager | |
52 * The entity manager service. | |
53 * @param \Drupal\Core\State\StateInterface $state | |
54 * The state service. | |
55 */ | |
56 public function __construct(Connection $database, AccountInterface $current_user, EntityManagerInterface $entity_manager, StateInterface $state) { | |
57 $this->database = $database; | |
58 $this->currentUser = $current_user; | |
59 $this->entityManager = $entity_manager; | |
60 $this->state = $state; | |
61 } | |
62 | |
63 /** | |
64 * {@inheritdoc} | |
65 */ | |
66 public function read($entities, $entity_type, $accurate = TRUE) { | |
67 $options = $accurate ? [] : ['target' => 'replica']; | |
68 $stats = $this->database->select('comment_entity_statistics', 'ces', $options) | |
69 ->fields('ces') | |
70 ->condition('ces.entity_id', array_keys($entities), 'IN') | |
71 ->condition('ces.entity_type', $entity_type) | |
72 ->execute(); | |
73 | |
74 $statistics_records = []; | |
75 while ($entry = $stats->fetchObject()) { | |
76 $statistics_records[] = $entry; | |
77 } | |
78 return $statistics_records; | |
79 } | |
80 | |
81 /** | |
82 * {@inheritdoc} | |
83 */ | |
84 public function delete(EntityInterface $entity) { | |
85 $this->database->delete('comment_entity_statistics') | |
86 ->condition('entity_id', $entity->id()) | |
87 ->condition('entity_type', $entity->getEntityTypeId()) | |
88 ->execute(); | |
89 } | |
90 | |
91 /** | |
92 * {@inheritdoc} | |
93 */ | |
94 public function create(FieldableEntityInterface $entity, $fields) { | |
95 $query = $this->database->insert('comment_entity_statistics') | |
96 ->fields([ | |
97 'entity_id', | |
98 'entity_type', | |
99 'field_name', | |
100 'cid', | |
101 'last_comment_timestamp', | |
102 'last_comment_name', | |
103 'last_comment_uid', | |
104 'comment_count', | |
105 ]); | |
106 foreach ($fields as $field_name => $detail) { | |
107 // Skip fields that entity does not have. | |
108 if (!$entity->hasField($field_name)) { | |
109 continue; | |
110 } | |
111 // Get the user ID from the entity if it's set, or default to the | |
112 // currently logged in user. | |
113 $last_comment_uid = 0; | |
114 if ($entity instanceof EntityOwnerInterface) { | |
115 $last_comment_uid = $entity->getOwnerId(); | |
116 } | |
117 if (!isset($last_comment_uid)) { | |
118 // Default to current user when entity does not implement | |
119 // EntityOwnerInterface or author is not set. | |
120 $last_comment_uid = $this->currentUser->id(); | |
121 } | |
122 // Default to REQUEST_TIME when entity does not have a changed property. | |
123 $last_comment_timestamp = REQUEST_TIME; | |
124 // @todo Make comment statistics language aware and add some tests. See | |
125 // https://www.drupal.org/node/2318875 | |
126 if ($entity instanceof EntityChangedInterface) { | |
127 $last_comment_timestamp = $entity->getChangedTimeAcrossTranslations(); | |
128 } | |
129 $query->values([ | |
130 'entity_id' => $entity->id(), | |
131 'entity_type' => $entity->getEntityTypeId(), | |
132 'field_name' => $field_name, | |
133 'cid' => 0, | |
134 'last_comment_timestamp' => $last_comment_timestamp, | |
135 'last_comment_name' => NULL, | |
136 'last_comment_uid' => $last_comment_uid, | |
137 'comment_count' => 0, | |
138 ]); | |
139 } | |
140 $query->execute(); | |
141 } | |
142 | |
143 /** | |
144 * {@inheritdoc} | |
145 */ | |
146 public function getMaximumCount($entity_type) { | |
147 return $this->database->query('SELECT MAX(comment_count) FROM {comment_entity_statistics} WHERE entity_type = :entity_type', [':entity_type' => $entity_type])->fetchField(); | |
148 } | |
149 | |
150 /** | |
151 * {@inheritdoc} | |
152 */ | |
153 public function getRankingInfo() { | |
154 return [ | |
155 'comments' => [ | |
156 'title' => t('Number of comments'), | |
157 'join' => [ | |
158 'type' => 'LEFT', | |
159 'table' => 'comment_entity_statistics', | |
160 'alias' => 'ces', | |
161 // Default to comment field as this is the most common use case for | |
162 // nodes. | |
163 'on' => "ces.entity_id = i.sid AND ces.entity_type = 'node' AND ces.field_name = 'comment'", | |
164 ], | |
165 // Inverse law that maps the highest view count on the site to 1 and 0 | |
166 // to 0. Note that the ROUND here is necessary for PostgreSQL and SQLite | |
167 // in order to ensure that the :comment_scale argument is treated as | |
168 // a numeric type, because the PostgreSQL PDO driver sometimes puts | |
169 // values in as strings instead of numbers in complex expressions like | |
170 // this. | |
171 'score' => '2.0 - 2.0 / (1.0 + ces.comment_count * (ROUND(:comment_scale, 4)))', | |
172 'arguments' => [':comment_scale' => \Drupal::state()->get('comment.node_comment_statistics_scale') ?: 0], | |
173 ], | |
174 ]; | |
175 } | |
176 | |
177 /** | |
178 * {@inheritdoc} | |
179 */ | |
180 public function update(CommentInterface $comment) { | |
181 // Allow bulk updates and inserts to temporarily disable the maintenance of | |
182 // the {comment_entity_statistics} table. | |
183 if (!$this->state->get('comment.maintain_entity_statistics')) { | |
184 return; | |
185 } | |
186 | |
187 $query = $this->database->select('comment_field_data', 'c'); | |
188 $query->addExpression('COUNT(cid)'); | |
189 $count = $query->condition('c.entity_id', $comment->getCommentedEntityId()) | |
190 ->condition('c.entity_type', $comment->getCommentedEntityTypeId()) | |
191 ->condition('c.field_name', $comment->getFieldName()) | |
192 ->condition('c.status', CommentInterface::PUBLISHED) | |
193 ->condition('default_langcode', 1) | |
194 ->execute() | |
195 ->fetchField(); | |
196 | |
197 if ($count > 0) { | |
198 // Comments exist. | |
199 $last_reply = $this->database->select('comment_field_data', 'c') | |
200 ->fields('c', ['cid', 'name', 'changed', 'uid']) | |
201 ->condition('c.entity_id', $comment->getCommentedEntityId()) | |
202 ->condition('c.entity_type', $comment->getCommentedEntityTypeId()) | |
203 ->condition('c.field_name', $comment->getFieldName()) | |
204 ->condition('c.status', CommentInterface::PUBLISHED) | |
205 ->condition('default_langcode', 1) | |
206 ->orderBy('c.created', 'DESC') | |
207 ->range(0, 1) | |
208 ->execute() | |
209 ->fetchObject(); | |
210 // Use merge here because entity could be created before comment field. | |
211 $this->database->merge('comment_entity_statistics') | |
212 ->fields([ | |
213 'cid' => $last_reply->cid, | |
214 'comment_count' => $count, | |
215 'last_comment_timestamp' => $last_reply->changed, | |
216 'last_comment_name' => $last_reply->uid ? '' : $last_reply->name, | |
217 'last_comment_uid' => $last_reply->uid, | |
218 ]) | |
219 ->keys([ | |
220 'entity_id' => $comment->getCommentedEntityId(), | |
221 'entity_type' => $comment->getCommentedEntityTypeId(), | |
222 'field_name' => $comment->getFieldName(), | |
223 ]) | |
224 ->execute(); | |
225 } | |
226 else { | |
227 // Comments do not exist. | |
228 $entity = $comment->getCommentedEntity(); | |
229 // Get the user ID from the entity if it's set, or default to the | |
230 // currently logged in user. | |
231 if ($entity instanceof EntityOwnerInterface) { | |
232 $last_comment_uid = $entity->getOwnerId(); | |
233 } | |
234 if (!isset($last_comment_uid)) { | |
235 // Default to current user when entity does not implement | |
236 // EntityOwnerInterface or author is not set. | |
237 $last_comment_uid = $this->currentUser->id(); | |
238 } | |
239 $this->database->update('comment_entity_statistics') | |
240 ->fields([ | |
241 'cid' => 0, | |
242 'comment_count' => 0, | |
243 // Use the changed date of the entity if it's set, or default to | |
244 // REQUEST_TIME. | |
245 'last_comment_timestamp' => ($entity instanceof EntityChangedInterface) ? $entity->getChangedTimeAcrossTranslations() : REQUEST_TIME, | |
246 'last_comment_name' => '', | |
247 'last_comment_uid' => $last_comment_uid, | |
248 ]) | |
249 ->condition('entity_id', $comment->getCommentedEntityId()) | |
250 ->condition('entity_type', $comment->getCommentedEntityTypeId()) | |
251 ->condition('field_name', $comment->getFieldName()) | |
252 ->execute(); | |
253 } | |
254 | |
255 // Reset the cache of the commented entity so that when the entity is loaded | |
256 // the next time, the statistics will be loaded again. | |
257 $this->entityManager->getStorage($comment->getCommentedEntityTypeId())->resetCache([$comment->getCommentedEntityId()]); | |
258 } | |
259 | |
260 } |