Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
53 / 53 |
|
100.00% |
8 / 8 |
CRAP | |
100.00% |
1 / 1 |
CounterService | |
100.00% |
53 / 53 |
|
100.00% |
8 / 8 |
10 | |
100.00% |
1 / 1 |
__construct | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
recordView | |
100.00% |
12 / 12 |
|
100.00% |
1 / 1 |
1 | |||
fetchViews | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
2 | |||
fetchView | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
fetchAll | |
100.00% |
9 / 9 |
|
100.00% |
1 / 1 |
1 | |||
resetDayCount | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
2 | |||
deleteViews | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
1 | |||
maxTotalCount | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
1 |
1 | <?php |
2 | |
3 | namespace Drupal\visitors\Service; |
4 | |
5 | use Drupal\Component\Datetime\TimeInterface; |
6 | use Drupal\Core\Database\Connection; |
7 | use Drupal\Core\State\StateInterface; |
8 | use Drupal\visitors\StatisticsViewsResult; |
9 | use Drupal\visitors\VisitorsCounterInterface; |
10 | |
11 | /** |
12 | * Counts entity views. |
13 | */ |
14 | class CounterService implements VisitorsCounterInterface { |
15 | |
16 | /** |
17 | * The number of seconds in one day. |
18 | */ |
19 | const ONE_DAY = 86400; |
20 | |
21 | /** |
22 | * The entities viewed. |
23 | * |
24 | * @var array |
25 | */ |
26 | protected static $entities = []; |
27 | |
28 | /** |
29 | * The database connection. |
30 | * |
31 | * @var \Drupal\Core\Database\Connection |
32 | */ |
33 | protected $database; |
34 | |
35 | /** |
36 | * The date service. |
37 | * |
38 | * @var \Drupal\Component\Datetime\TimeInterface |
39 | */ |
40 | protected $time; |
41 | |
42 | /** |
43 | * The state service. |
44 | * |
45 | * @var \Drupal\Core\State\StateInterface |
46 | */ |
47 | protected $state; |
48 | |
49 | /** |
50 | * Constructs the counter service. |
51 | * |
52 | * @param \Drupal\Core\Database\Connection $connection |
53 | * The database connection for the node view storage. |
54 | * @param \Drupal\Component\Datetime\TimeInterface $time |
55 | * The date service. |
56 | * @param \Drupal\Core\State\StateInterface $state |
57 | * The state service. |
58 | */ |
59 | public function __construct(Connection $connection, TimeInterface $time, StateInterface $state) { |
60 | $this->database = $connection; |
61 | $this->time = $time; |
62 | $this->state = $state; |
63 | } |
64 | |
65 | /** |
66 | * {@inheritdoc} |
67 | */ |
68 | public function recordView(string $type, int $id) { |
69 | return (bool) $this->database |
70 | ->merge('visitors_counter') |
71 | ->key('entity_type', $type) |
72 | ->key('entity_id', $id) |
73 | ->fields([ |
74 | 'today' => 1, |
75 | 'total' => 1, |
76 | 'timestamp' => $this->time->getRequestTime(), |
77 | ]) |
78 | ->expression('today', '[today] + 1') |
79 | ->expression('total', '[total] + 1') |
80 | ->execute(); |
81 | } |
82 | |
83 | /** |
84 | * {@inheritdoc} |
85 | */ |
86 | public function fetchViews(string $type, array $ids): array { |
87 | $views = $this->database |
88 | ->select('visitors_counter', 'vc') |
89 | ->fields('vc', ['total', 'today', 'timestamp']) |
90 | ->condition('entity_type', $type) |
91 | ->condition('entity_id', $ids, 'IN') |
92 | ->execute() |
93 | ->fetchAll(); |
94 | foreach ($views as $id => $view) { |
95 | $views[$id] = new StatisticsViewsResult($view->total, $view->today, $view->timestamp); |
96 | } |
97 | return $views; |
98 | } |
99 | |
100 | /** |
101 | * {@inheritdoc} |
102 | */ |
103 | public function fetchView(string $type, int $id) { |
104 | $views = $this->fetchViews($type, [$id]); |
105 | return reset($views); |
106 | } |
107 | |
108 | /** |
109 | * {@inheritdoc} |
110 | */ |
111 | public function fetchAll(string $type, string $order = 'total', int $limit = 5) { |
112 | assert(in_array($order, ['total', 'today', 'timestamp']), "Invalid order argument."); |
113 | |
114 | return $this->database |
115 | ->select('visitors_counter', 'vc') |
116 | ->fields('vc', ['entity_id']) |
117 | ->condition('entity_type', $type) |
118 | ->orderBy($order, 'DESC') |
119 | ->range(0, $limit) |
120 | ->execute() |
121 | ->fetchCol(); |
122 | } |
123 | |
124 | /** |
125 | * {@inheritdoc} |
126 | */ |
127 | public function resetDayCount() { |
128 | $counter_timestamp = $this->state->get('visitors.count_timestamp', 0); |
129 | $now = $this->time->getRequestTime(); |
130 | if (($now - $counter_timestamp) >= self::ONE_DAY) { |
131 | $this->state->set('visitors.count_timestamp', $now); |
132 | $this->database->update('visitors_counter') |
133 | ->fields(['today' => 0]) |
134 | ->execute(); |
135 | } |
136 | } |
137 | |
138 | /** |
139 | * {@inheritdoc} |
140 | */ |
141 | public function deleteViews(string $type, int $id) { |
142 | return (bool) $this->database |
143 | ->delete('visitors_counter') |
144 | ->condition('entity_type', $type) |
145 | ->condition('entity_id', $id) |
146 | ->execute(); |
147 | } |
148 | |
149 | /** |
150 | * {@inheritdoc} |
151 | */ |
152 | public function maxTotalCount(string $type) { |
153 | $query = $this->database->select('visitors_counter', 'vc'); |
154 | $query->addExpression('MAX([total])'); |
155 | $query->condition('entity_type', $type); |
156 | $max_total_count = (int) $query->execute()->fetchField(); |
157 | return $max_total_count; |
158 | } |
159 | |
160 | } |