Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
28.57% |
2 / 7 |
CRAP | |
14.71% |
15 / 102 |
CommentStatistics | |
0.00% |
0 / 1 |
|
28.57% |
2 / 7 |
294.65 | |
14.71% |
15 / 102 |
__construct | |
100.00% |
1 / 1 |
1 | |
100.00% |
5 / 5 |
|||
read | |
100.00% |
1 / 1 |
3 | |
100.00% |
10 / 10 |
|||
delete | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 5 |
|||
create | |
0.00% |
0 / 1 |
42 | |
0.00% |
0 / 24 |
|||
getMaximumCount | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
getRankingInfo | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 4 |
|||
update | |
0.00% |
0 / 1 |
56 | |
0.00% |
0 / 53 |
<?php | |
/** | |
* @file | |
* Contains \Drupal\comment\CommentStatistics. | |
*/ | |
namespace Drupal\comment; | |
use Drupal\Core\Database\Connection; | |
use Drupal\Core\Entity\FieldableEntityInterface; | |
use Drupal\Core\Entity\EntityChangedInterface; | |
use Drupal\Core\Entity\EntityInterface; | |
use Drupal\Core\Entity\EntityManagerInterface; | |
use Drupal\Core\State\StateInterface; | |
use Drupal\Core\Session\AccountInterface; | |
use Drupal\user\EntityOwnerInterface; | |
class CommentStatistics implements CommentStatisticsInterface { | |
/** | |
* The current database connection. | |
* | |
* @var \Drupal\Core\Database\Connection | |
*/ | |
protected $database; | |
/** | |
* The current logged in user. | |
* | |
* @var \Drupal\Core\Session\AccountInterface | |
*/ | |
protected $currentUser; | |
/** | |
* The entity manager service. | |
* | |
* @var \Drupal\Core\Entity\EntityManagerInterface | |
*/ | |
protected $entityManager; | |
/** | |
* The state service. | |
* | |
* @var \Drupal\Core\State\StateInterface | |
*/ | |
protected $state; | |
/** | |
* Constructs the CommentStatistics service. | |
* | |
* @param \Drupal\Core\Database\Connection $database | |
* The active database connection. | |
* @param \Drupal\Core\Session\AccountInterface $current_user | |
* The current logged in user. | |
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager | |
* The entity manager service. | |
* @param \Drupal\Core\State\StateInterface $state | |
* The state service. | |
*/ | |
public function __construct(Connection $database, AccountInterface $current_user, EntityManagerInterface $entity_manager, StateInterface $state) { | |
$this->database = $database; | |
$this->currentUser = $current_user; | |
$this->entityManager = $entity_manager; | |
$this->state = $state; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function read($entities, $entity_type, $accurate = TRUE) { | |
$options = $accurate ? array() : array('target' => 'replica'); | |
$stats = $this->database->select('comment_entity_statistics', 'ces', $options) | |
->fields('ces') | |
->condition('ces.entity_id', array_keys($entities), 'IN') | |
->condition('ces.entity_type', $entity_type) | |
->execute(); | |
$statistics_records = array(); | |
while ($entry = $stats->fetchObject()) { | |
$statistics_records[] = $entry; | |
} | |
return $statistics_records; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function delete(EntityInterface $entity) { | |
$this->database->delete('comment_entity_statistics') | |
->condition('entity_id', $entity->id()) | |
->condition('entity_type', $entity->getEntityTypeId()) | |
->execute(); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function create(FieldableEntityInterface $entity, $fields) { | |
$query = $this->database->insert('comment_entity_statistics') | |
->fields(array( | |
'entity_id', | |
'entity_type', | |
'field_name', | |
'cid', | |
'last_comment_timestamp', | |
'last_comment_name', | |
'last_comment_uid', | |
'comment_count', | |
)); | |
foreach ($fields as $field_name => $detail) { | |
// Skip fields that entity does not have. | |
if (!$entity->hasField($field_name)) { | |
continue; | |
} | |
// Get the user ID from the entity if it's set, or default to the | |
// currently logged in user. | |
$last_comment_uid = 0; | |
if ($entity instanceof EntityOwnerInterface) { | |
$last_comment_uid = $entity->getOwnerId(); | |
} | |
if (!isset($last_comment_uid)) { | |
// Default to current user when entity does not implement | |
// EntityOwnerInterface or author is not set. | |
$last_comment_uid = $this->currentUser->id(); | |
} | |
// Default to REQUEST_TIME when entity does not have a changed property. | |
$last_comment_timestamp = REQUEST_TIME; | |
// @todo Make comment statistics language aware and add some tests. See | |
// https://www.drupal.org/node/2318875 | |
if ($entity instanceof EntityChangedInterface) { | |
$last_comment_timestamp = $entity->getChangedTimeAcrossTranslations(); | |
} | |
$query->values(array( | |
'entity_id' => $entity->id(), | |
'entity_type' => $entity->getEntityTypeId(), | |
'field_name' => $field_name, | |
'cid' => 0, | |
'last_comment_timestamp' => $last_comment_timestamp, | |
'last_comment_name' => NULL, | |
'last_comment_uid' => $last_comment_uid, | |
'comment_count' => 0, | |
)); | |
} | |
$query->execute(); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function getMaximumCount($entity_type) { | |
return $this->database->query('SELECT MAX(comment_count) FROM {comment_entity_statistics} WHERE entity_type = :entity_type', array(':entity_type' => $entity_type))->fetchField(); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function getRankingInfo() { | |
return array( | |
'comments' => array( | |
'title' => t('Number of comments'), | |
'join' => array( | |
'type' => 'LEFT', | |
'table' => 'comment_entity_statistics', | |
'alias' => 'ces', | |
// Default to comment field as this is the most common use case for | |
// nodes. | |
'on' => "ces.entity_id = i.sid AND ces.entity_type = 'node' AND ces.field_name = 'comment'", | |
), | |
// Inverse law that maps the highest view count on the site to 1 and 0 | |
// to 0. Note that the ROUND here is necessary for PostgreSQL and SQLite | |
// in order to ensure that the :comment_scale argument is treated as | |
// a numeric type, because the PostgreSQL PDO driver sometimes puts | |
// values in as strings instead of numbers in complex expressions like | |
// this. | |
'score' => '2.0 - 2.0 / (1.0 + ces.comment_count * (ROUND(:comment_scale, 4)))', | |
'arguments' => array(':comment_scale' => \Drupal::state()->get('comment.node_comment_statistics_scale') ?: 0), | |
), | |
); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function update(CommentInterface $comment) { | |
// Allow bulk updates and inserts to temporarily disable the maintenance of | |
// the {comment_entity_statistics} table. | |
if (!$this->state->get('comment.maintain_entity_statistics')) { | |
return; | |
} | |
$query = $this->database->select('comment_field_data', 'c'); | |
$query->addExpression('COUNT(cid)'); | |
$count = $query->condition('c.entity_id', $comment->getCommentedEntityId()) | |
->condition('c.entity_type', $comment->getCommentedEntityTypeId()) | |
->condition('c.field_name', $comment->getFieldName()) | |
->condition('c.status', CommentInterface::PUBLISHED) | |
->condition('default_langcode', 1) | |
->execute() | |
->fetchField(); | |
if ($count > 0) { | |
// Comments exist. | |
$last_reply = $this->database->select('comment_field_data', 'c') | |
->fields('c', array('cid', 'name', 'changed', 'uid')) | |
->condition('c.entity_id', $comment->getCommentedEntityId()) | |
->condition('c.entity_type', $comment->getCommentedEntityTypeId()) | |
->condition('c.field_name', $comment->getFieldName()) | |
->condition('c.status', CommentInterface::PUBLISHED) | |
->condition('default_langcode', 1) | |
->orderBy('c.created', 'DESC') | |
->range(0, 1) | |
->execute() | |
->fetchObject(); | |
// Use merge here because entity could be created before comment field. | |
$this->database->merge('comment_entity_statistics') | |
->fields(array( | |
'cid' => $last_reply->cid, | |
'comment_count' => $count, | |
'last_comment_timestamp' => $last_reply->changed, | |
'last_comment_name' => $last_reply->uid ? '' : $last_reply->name, | |
'last_comment_uid' => $last_reply->uid, | |
)) | |
->keys(array( | |
'entity_id' => $comment->getCommentedEntityId(), | |
'entity_type' => $comment->getCommentedEntityTypeId(), | |
'field_name' => $comment->getFieldName(), | |
)) | |
->execute(); | |
} | |
else { | |
// Comments do not exist. | |
$entity = $comment->getCommentedEntity(); | |
// Get the user ID from the entity if it's set, or default to the | |
// currently logged in user. | |
if ($entity instanceof EntityOwnerInterface) { | |
$last_comment_uid = $entity->getOwnerId(); | |
} | |
if (!isset($last_comment_uid)) { | |
// Default to current user when entity does not implement | |
// EntityOwnerInterface or author is not set. | |
$last_comment_uid = $this->currentUser->id(); | |
} | |
$this->database->update('comment_entity_statistics') | |
->fields(array( | |
'cid' => 0, | |
'comment_count' => 0, | |
// Use the changed date of the entity if it's set, or default to | |
// REQUEST_TIME. | |
'last_comment_timestamp' => ($entity instanceof EntityChangedInterface) ? $entity->getChangedTimeAcrossTranslations() : REQUEST_TIME, | |
'last_comment_name' => '', | |
'last_comment_uid' => $last_comment_uid, | |
)) | |
->condition('entity_id', $comment->getCommentedEntityId()) | |
->condition('entity_type', $comment->getCommentedEntityTypeId()) | |
->condition('field_name', $comment->getFieldName()) | |
->execute(); | |
} | |
// Reset the cache of the commented entity so that when the entity is loaded | |
// the next time, the statistics will be loaded again. | |
$this->entityManager->getStorage($comment->getCommentedEntityTypeId())->resetCache(array($comment->getCommentedEntityId())); | |
} | |
} |