Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
106 / 106 |
|
100.00% |
10 / 10 |
CRAP | |
100.00% |
1 / 1 |
VisitorsPopularBlock | |
100.00% |
106 / 106 |
|
100.00% |
10 / 10 |
20 | |
100.00% |
1 / 1 |
__construct | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
1 | |||
create | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
1 | |||
defaultConfiguration | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
1 | |||
blockAccess | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
3 | |||
blockForm | |
100.00% |
31 / 31 |
|
100.00% |
1 / 1 |
1 | |||
entityTypes | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
3 | |||
blockSubmit | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
build | |
100.00% |
17 / 17 |
|
100.00% |
1 / 1 |
6 | |||
entityLabelList | |
100.00% |
16 / 16 |
|
100.00% |
1 / 1 |
2 | |||
getCacheTags | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 |
1 | <?php |
2 | |
3 | namespace Drupal\visitors\Plugin\Block; |
4 | |
5 | use Drupal\Core\Access\AccessResult; |
6 | use Drupal\Core\Block\BlockBase; |
7 | use Drupal\Core\Config\ConfigFactoryInterface; |
8 | use Drupal\Core\Entity\EntityRepositoryInterface; |
9 | use Drupal\Core\Entity\EntityTypeManagerInterface; |
10 | use Drupal\Core\Form\FormStateInterface; |
11 | use Drupal\Core\Plugin\ContainerFactoryPluginInterface; |
12 | use Drupal\Core\Render\RendererInterface; |
13 | use Drupal\Core\Session\AccountInterface; |
14 | use Drupal\visitors\VisitorsCounterInterface; |
15 | use Symfony\Component\DependencyInjection\ContainerInterface; |
16 | |
17 | /** |
18 | * Provides a 'Popular content' block. |
19 | * |
20 | * @Block( |
21 | * id = "visitors_popular_block", |
22 | * admin_label = @Translation("Popular content") |
23 | * ) |
24 | */ |
25 | final class VisitorsPopularBlock extends BlockBase implements ContainerFactoryPluginInterface { |
26 | |
27 | /** |
28 | * The entity type manager. |
29 | * |
30 | * @var \Drupal\Core\Entity\EntityTypeManagerInterface |
31 | */ |
32 | protected $entityTypeManager; |
33 | |
34 | /** |
35 | * The entity repository service. |
36 | * |
37 | * @var \Drupal\Core\Entity\EntityRepositoryInterface |
38 | */ |
39 | protected $entityRepository; |
40 | |
41 | /** |
42 | * The storage for visitor counter. |
43 | * |
44 | * @var \Drupal\visitors\VisitorsCounterInterface |
45 | */ |
46 | protected $statisticsStorage; |
47 | |
48 | /** |
49 | * The renderer interface. |
50 | * |
51 | * @var \Drupal\Core\Render\RendererInterface |
52 | */ |
53 | protected $renderer; |
54 | |
55 | /** |
56 | * The config factory. |
57 | * |
58 | * @var \Drupal\Core\Config\ConfigFactoryInterface |
59 | */ |
60 | protected $configFactory; |
61 | |
62 | /** |
63 | * Constructs a StatisticsPopularBlock object. |
64 | * |
65 | * @param array $configuration |
66 | * A configuration array containing information about the plugin instance. |
67 | * @param string $plugin_id |
68 | * The plugin_id for the plugin instance. |
69 | * @param mixed $plugin_definition |
70 | * The plugin implementation definition. |
71 | * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager |
72 | * The entity type manager. |
73 | * @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository |
74 | * The entity repository service. |
75 | * @param \Drupal\visitors\VisitorsCounterInterface $statistics_storage |
76 | * The storage for statistics. |
77 | * @param \Drupal\Core\Render\RendererInterface $renderer |
78 | * The renderer configuration array. |
79 | * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory |
80 | * The config factory. |
81 | */ |
82 | public function __construct( |
83 | array $configuration, |
84 | $plugin_id, |
85 | $plugin_definition, |
86 | EntityTypeManagerInterface $entity_type_manager, |
87 | EntityRepositoryInterface $entity_repository, |
88 | VisitorsCounterInterface $statistics_storage, |
89 | RendererInterface $renderer, |
90 | ConfigFactoryInterface $config_factory, |
91 | ) { |
92 | parent::__construct($configuration, $plugin_id, $plugin_definition); |
93 | $this->entityTypeManager = $entity_type_manager; |
94 | $this->entityRepository = $entity_repository; |
95 | $this->statisticsStorage = $statistics_storage; |
96 | $this->renderer = $renderer; |
97 | $this->configFactory = $config_factory; |
98 | } |
99 | |
100 | /** |
101 | * {@inheritdoc} |
102 | */ |
103 | public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { |
104 | return new self( |
105 | $configuration, |
106 | $plugin_id, |
107 | $plugin_definition, |
108 | $container->get('entity_type.manager'), |
109 | $container->get('entity.repository'), |
110 | $container->get('visitors.counter'), |
111 | $container->get('renderer'), |
112 | $container->get('config.factory'), |
113 | ); |
114 | } |
115 | |
116 | /** |
117 | * {@inheritdoc} |
118 | */ |
119 | public function defaultConfiguration() { |
120 | return [ |
121 | 'top_day_num' => 0, |
122 | 'top_all_num' => 0, |
123 | 'top_last_num' => 0, |
124 | 'entity_type' => 'node', |
125 | ]; |
126 | } |
127 | |
128 | /** |
129 | * {@inheritdoc} |
130 | */ |
131 | protected function blockAccess(AccountInterface $account) { |
132 | $settings = $this->configFactory->get('visitors.config'); |
133 | $entity_type = $this->configuration['entity_type'] ?? ''; |
134 | $allowed_entity_types = $settings->get('counter.entity_types'); |
135 | $disabled_or_entity_type_not_allowed = !$settings->get('counter.enabled') || !in_array($entity_type, $allowed_entity_types); |
136 | if ($disabled_or_entity_type_not_allowed) { |
137 | return AccessResult::forbidden(); |
138 | } |
139 | |
140 | return AccessResult::allowedIfHasPermission($account, 'access content'); |
141 | } |
142 | |
143 | /** |
144 | * {@inheritdoc} |
145 | */ |
146 | public function blockForm($form, FormStateInterface $form_state) { |
147 | // Popular content block settings. |
148 | $numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 40]; |
149 | $numbers = ['0' => $this->t('Disabled')] + array_combine($numbers, $numbers); |
150 | $form['statistics_block_top_day_num'] = [ |
151 | '#type' => 'select', |
152 | '#title' => $this->t("Number of day's top views to display"), |
153 | '#default_value' => $this->configuration['top_day_num'], |
154 | '#options' => $numbers, |
155 | '#description' => $this->t('How many content items to display in "day" list.'), |
156 | ]; |
157 | $form['statistics_block_top_all_num'] = [ |
158 | '#type' => 'select', |
159 | '#title' => $this->t('Number of all time views to display'), |
160 | '#default_value' => $this->configuration['top_all_num'], |
161 | '#options' => $numbers, |
162 | '#description' => $this->t('How many content items to display in "all time" list.'), |
163 | ]; |
164 | $form['statistics_block_top_last_num'] = [ |
165 | '#type' => 'select', |
166 | '#title' => $this->t('Number of most recent views to display'), |
167 | '#default_value' => $this->configuration['top_last_num'], |
168 | '#options' => $numbers, |
169 | '#description' => $this->t('How many content items to display in "recently viewed" list.'), |
170 | ]; |
171 | $form['entity_type'] = [ |
172 | '#type' => 'radios', |
173 | '#title' => $this->t('Entity types'), |
174 | '#options' => $this->entityTypes(), |
175 | '#default_value' => $this->configuration['entity_type'] ?? 'node', |
176 | '#description' => $this->t('Select entity types to display popular content.'), |
177 | ]; |
178 | |
179 | return $form; |
180 | } |
181 | |
182 | /** |
183 | * Returns a list of entity types. |
184 | */ |
185 | protected function entityTypes() { |
186 | $allowed_entity_types = $this->configFactory->get('visitors.config')->get('counter.entity_types'); |
187 | $entity_types_list = []; |
188 | $entity_definitions = $this->entityTypeManager->getDefinitions(); |
189 | foreach ($entity_definitions as $entity_name => $entity_definition) { |
190 | if (!in_array($entity_name, $allowed_entity_types)) { |
191 | continue; |
192 | } |
193 | $entity_types_list[$entity_name] = (string) $entity_definition->getLabel(); |
194 | } |
195 | asort($entity_types_list); |
196 | |
197 | return $entity_types_list; |
198 | } |
199 | |
200 | /** |
201 | * {@inheritdoc} |
202 | */ |
203 | public function blockSubmit($form, FormStateInterface $form_state) { |
204 | $this->configuration['top_day_num'] = $form_state->getValue('statistics_block_top_day_num'); |
205 | $this->configuration['top_all_num'] = $form_state->getValue('statistics_block_top_all_num'); |
206 | $this->configuration['top_last_num'] = $form_state->getValue('statistics_block_top_last_num'); |
207 | $this->configuration['entity_type'] = $form_state->getValue('entity_type'); |
208 | } |
209 | |
210 | /** |
211 | * {@inheritdoc} |
212 | */ |
213 | public function build() { |
214 | $content = []; |
215 | $entity_type = 'node'; |
216 | if ($this->configuration['top_day_num'] > 0) { |
217 | $ids = $this->statisticsStorage->fetchAll($entity_type, 'today', $this->configuration['top_day_num']); |
218 | if ($ids) { |
219 | $content['top_day'] = $this->entityLabelList($ids, $this->t("Today's:")); |
220 | $content['top_day']['#suffix'] = '<br />'; |
221 | } |
222 | } |
223 | |
224 | if ($this->configuration['top_all_num'] > 0) { |
225 | $ids = $this->statisticsStorage->fetchAll($entity_type, 'total', $this->configuration['top_all_num']); |
226 | if ($ids) { |
227 | $content['top_all'] = $this->entityLabelList($ids, $this->t('All time:')); |
228 | $content['top_all']['#suffix'] = '<br />'; |
229 | } |
230 | } |
231 | |
232 | if ($this->configuration['top_last_num'] > 0) { |
233 | $ids = $this->statisticsStorage->fetchAll($entity_type, 'timestamp', $this->configuration['top_last_num']); |
234 | $content['top_last'] = $this->entityLabelList($ids, $this->t('Last viewed:')); |
235 | $content['top_last']['#suffix'] = '<br />'; |
236 | } |
237 | |
238 | return $content; |
239 | } |
240 | |
241 | /** |
242 | * Generates the ordered array of entity links for build(). |
243 | * |
244 | * @param int[] $ids |
245 | * An ordered array of entity ids. |
246 | * @param string $title |
247 | * The title for the list. |
248 | * |
249 | * @return array |
250 | * A render array for the list. |
251 | */ |
252 | protected function entityLabelList(array $ids, $title) { |
253 | $entity_type = $this->configuration['entity_type'] ?? 'node'; |
254 | $entities = $this->entityTypeManager->getStorage($entity_type)->loadMultiple($ids); |
255 | |
256 | $items = []; |
257 | foreach ($ids as $id) { |
258 | $entity = $this->entityRepository->getTranslationFromContext($entities[$id]); |
259 | $item = $entity->toLink()->toRenderable(); |
260 | $this->renderer->addCacheableDependency($item, $entity); |
261 | $items[] = $item; |
262 | } |
263 | |
264 | return [ |
265 | '#theme' => 'item_list', |
266 | '#items' => $items, |
267 | '#title' => $title, |
268 | '#cache' => [ |
269 | 'tags' => $this->entityTypeManager->getDefinition($entity_type)->getListCacheTags(), |
270 | ], |
271 | ]; |
272 | } |
273 | |
274 | /** |
275 | * {@inheritdoc} |
276 | */ |
277 | public function getCacheTags() { |
278 | return ['config:visitors.config']; |
279 | } |
280 | |
281 | } |