Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
278 / 278 |
|
100.00% |
8 / 8 |
CRAP | |
100.00% |
1 / 1 |
Settings | |
100.00% |
278 / 278 |
|
100.00% |
8 / 8 |
17 | |
100.00% |
1 / 1 |
__construct | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
create | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
getFormId | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getEditableConfigNames | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
buildForm | |
100.00% |
236 / 236 |
|
100.00% |
1 / 1 |
7 | |||
submitForm | |
100.00% |
20 / 20 |
|
100.00% |
1 / 1 |
1 | |||
entityTypes | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
3 | |||
roleOptions | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace Drupal\visitors\Form; |
4 | |
5 | use Drupal\Core\Config\Entity\ConfigEntityType; |
6 | use Drupal\Core\Entity\EntityTypeManagerInterface; |
7 | use Drupal\Core\Extension\ThemeExtensionList; |
8 | use Drupal\Core\Form\ConfigFormBase; |
9 | use Drupal\Core\Form\FormStateInterface; |
10 | use Drupal\Core\Url; |
11 | use Drupal\visitors\VisitorsVisibilityInterface; |
12 | use Symfony\Component\DependencyInjection\ContainerInterface; |
13 | |
14 | /** |
15 | * Visitors Settings Form. |
16 | */ |
17 | class Settings extends ConfigFormBase { |
18 | |
19 | /** |
20 | * Config settings. |
21 | * |
22 | * @var string |
23 | */ |
24 | const SETTINGS = 'visitors.config'; |
25 | |
26 | /** |
27 | * An extension discovery instance. |
28 | * |
29 | * @var \Drupal\Core\Extension\ThemeExtensionList |
30 | */ |
31 | protected $themeList; |
32 | |
33 | /** |
34 | * An extension discovery instance. |
35 | * |
36 | * @var \Drupal\Core\Entity\EntityTypeManagerInterface |
37 | */ |
38 | protected $entityTypeManager; |
39 | |
40 | /** |
41 | * Constructs a Settings form. |
42 | * |
43 | * @param \Drupal\Core\Extension\ThemeExtensionList $theme_list |
44 | * The theme list. |
45 | * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager |
46 | * The entity type manager. |
47 | */ |
48 | public function __construct(ThemeExtensionList $theme_list, EntityTypeManagerInterface $entity_type_manager) { |
49 | $this->themeList = $theme_list; |
50 | $this->entityTypeManager = $entity_type_manager; |
51 | } |
52 | |
53 | /** |
54 | * {@inheritdoc} |
55 | */ |
56 | public static function create(ContainerInterface $container) { |
57 | return new self( |
58 | $container->get('extension.list.theme'), |
59 | $container->get('entity_type.manager') |
60 | ); |
61 | } |
62 | |
63 | /** |
64 | * {@inheritdoc} |
65 | */ |
66 | public function getFormId() { |
67 | return 'visitors_admin_settings'; |
68 | } |
69 | |
70 | /** |
71 | * {@inheritdoc} |
72 | */ |
73 | protected function getEditableConfigNames() { |
74 | return [ |
75 | static::SETTINGS, |
76 | ]; |
77 | } |
78 | |
79 | /** |
80 | * {@inheritdoc} |
81 | */ |
82 | public function buildForm(array $form, FormStateInterface $form_state) { |
83 | $config = $this->config('visitors.config'); |
84 | $system_config = $this->config('system.theme'); |
85 | $form = parent::buildForm($form, $form_state); |
86 | |
87 | $form['#attached']['library'][] = 'visitors/visitors.admin'; |
88 | |
89 | $roles = []; |
90 | foreach ($this->entityTypeManager->getStorage('user_role')->loadMultiple() as $name => $role) { |
91 | $roles[$name] = $role->label(); |
92 | } |
93 | |
94 | $all_themes = $this->themeList->getList(); |
95 | $default_theme = $system_config->get('default'); |
96 | $admin_theme = $system_config->get('admin'); |
97 | |
98 | $default_name = $all_themes[$default_theme]->info['name']; |
99 | $themes_installed = [ |
100 | 'default' => $this->t('Default (@default)', ['@default' => $default_name]), |
101 | ]; |
102 | if ($admin_theme) { |
103 | $admin_name = $all_themes[$admin_theme]->info['name']; |
104 | $themes_installed['admin'] = $this->t('Admin (@admin)', ['@admin' => $admin_name]); |
105 | } |
106 | |
107 | $list_themes = array_filter($all_themes, function ($obj) { |
108 | $a = get_object_vars($obj); |
109 | return $a['status'] ?? FALSE; |
110 | }); |
111 | $themes_installed += array_map(function ($value) { |
112 | return $value->info['name']; |
113 | }, $list_themes); |
114 | |
115 | $form['visitors_disable_tracking'] = [ |
116 | '#type' => 'radios', |
117 | '#title' => $this->t('Track visitors'), |
118 | '#options' => [ |
119 | $this->t('Enabled'), |
120 | $this->t('Disabled'), |
121 | ], |
122 | '#description' => $this->t('Enable or disable tracking of visitors.'), |
123 | '#default_value' => (int) $config->get('disable_tracking'), |
124 | ]; |
125 | |
126 | $form['theme'] = [ |
127 | '#type' => 'select', |
128 | '#title' => $this->t('Set a theme for reports'), |
129 | '#options' => $themes_installed, |
130 | '#default_value' => $config->get('theme') ?: 'admin', |
131 | '#description' => $this->t('Select a theme for the Visitors reports.'), |
132 | ]; |
133 | |
134 | // Visibility settings. |
135 | $form['tracking_scope'] = [ |
136 | '#type' => 'vertical_tabs', |
137 | '#title' => $this->t('Tracking scope'), |
138 | '#title_display' => 'invisible', |
139 | '#default_tab' => 'edit-tracking', |
140 | ]; |
141 | |
142 | // Page specific visibility configurations. |
143 | $visibility_request_path_pages = $config->get('visibility.request_path_pages'); |
144 | |
145 | $form['page_visibility_settings'] = [ |
146 | '#type' => 'details', |
147 | '#title' => $this->t('Pages'), |
148 | '#group' => 'tracking_scope', |
149 | ]; |
150 | |
151 | $description = $this->t( |
152 | "Specify pages by using their paths. Enter one path per line. The '*' character is a wildcard. Example paths are %blog for the blog page and %blog-wildcard for every personal blog. %front is the front page.", |
153 | [ |
154 | '%blog' => '/blog', |
155 | '%blog-wildcard' => '/blog/*', |
156 | '%front' => '<front>', |
157 | ] |
158 | ); |
159 | |
160 | $form['page_visibility_settings']['visitors_visibility_request_path_pages'] = [ |
161 | '#type' => 'textarea', |
162 | '#title' => $this->t('Pages'), |
163 | '#title_display' => 'invisible', |
164 | '#default_value' => !empty($visibility_request_path_pages) ? $visibility_request_path_pages : '', |
165 | '#description' => $description, |
166 | '#rows' => (int) 10, |
167 | ]; |
168 | $form['page_visibility_settings']['visitors_visibility_request_path_mode'] = [ |
169 | '#type' => 'radios', |
170 | '#title' => $this->t('Add tracking to specific pages'), |
171 | '#title_display' => 'invisible', |
172 | '#options' => [ |
173 | VisitorsVisibilityInterface::PATH_EXCLUDE => $this->t('All pages except those listed'), |
174 | VisitorsVisibilityInterface::PATH_INCLUDE => $this->t('Only the listed pages'), |
175 | ], |
176 | '#default_value' => $config->get('visibility.request_path_mode'), |
177 | ]; |
178 | |
179 | // Render the role overview. |
180 | $visibility_user_role_roles = $config->get('visibility.user_role_roles'); |
181 | |
182 | $form['role_visibility_settings'] = [ |
183 | '#type' => 'details', |
184 | '#title' => $this->t('Roles'), |
185 | '#group' => 'tracking_scope', |
186 | ]; |
187 | |
188 | $form['role_visibility_settings']['visitors_visibility_user_role_mode'] = [ |
189 | '#type' => 'radios', |
190 | '#title' => $this->t('Add tracking for specific roles'), |
191 | '#options' => [ |
192 | $this->t('Add to the selected roles only'), |
193 | $this->t('Add to every role except the selected ones'), |
194 | ], |
195 | '#default_value' => $config->get('visibility.user_role_mode'), |
196 | ]; |
197 | $form['role_visibility_settings']['visitors_visibility_user_role_roles'] = [ |
198 | '#type' => 'checkboxes', |
199 | '#title' => $this->t('Roles'), |
200 | '#default_value' => !empty($visibility_user_role_roles) ? $visibility_user_role_roles : [], |
201 | '#options' => $this->roleOptions(), |
202 | '#description' => $this->t('If none of the roles are selected, all users will be tracked. If a user has any of the roles checked, that user will be tracked (or excluded, depending on the setting above).'), |
203 | ]; |
204 | |
205 | $form['user_visibility_settings'] = [ |
206 | '#type' => 'details', |
207 | '#title' => $this->t('Users'), |
208 | '#group' => 'tracking_scope', |
209 | ]; |
210 | $t_permission = ['%permission' => $this->t('opt-out of visitors tracking')]; |
211 | $form['user_visibility_settings']['visitors_visibility_user_account_mode'] = [ |
212 | '#type' => 'radios', |
213 | '#title' => $this->t('Allow users to customize tracking on their account page'), |
214 | '#options' => [ |
215 | VisitorsVisibilityInterface::USER_NO_PERSONALIZATION => $this->t('No customization allowed'), |
216 | VisitorsVisibilityInterface::USER_OPT_OUT => $this->t('Tracking on by default, users with %permission permission can opt out', $t_permission), |
217 | VisitorsVisibilityInterface::USER_OPT_IN => $this->t('Tracking off by default, users with %permission permission can opt in', $t_permission), |
218 | ], |
219 | '#default_value' => $config->get('visibility.user_account_mode') ?? 0, |
220 | ]; |
221 | $form['user_visibility_settings']['visitors_trackuserid'] = [ |
222 | '#type' => 'checkbox', |
223 | '#title' => $this->t('Track User ID'), |
224 | '#default_value' => $config->get('track.userid'), |
225 | '#description' => $this->t('User ID enables the analysis of groups of sessions, across devices, using a unique, persistent, and representing a user. <a href=":url">Learn more about the benefits of using User ID</a>.', [':url' => 'https://matomo.org/docs/user-id/']), |
226 | ]; |
227 | |
228 | $form['user_visibility_settings']['visibility_exclude_user1'] = [ |
229 | '#type' => 'checkbox', |
230 | '#title' => $this->t('Exclude user1 from statistics'), |
231 | '#default_value' => $config->get('visibility.exclude_user1'), |
232 | '#description' => $this->t('Exclude hits of user1 from statistics.'), |
233 | ]; |
234 | |
235 | $form['entity'] = [ |
236 | '#type' => 'details', |
237 | '#title' => $this->t('Entity counter'), |
238 | '#group' => 'tracking_scope', |
239 | ]; |
240 | $form['entity']['counter_enabled'] = [ |
241 | '#type' => 'checkbox', |
242 | '#title' => $this->t('Enabled'), |
243 | '#default_value' => $config->get('counter.enabled'), |
244 | '#description' => $this->t('Count the number of times entities are viewed.'), |
245 | ]; |
246 | $form['entity']['entity_types'] = [ |
247 | '#type' => 'checkboxes', |
248 | '#title' => $this->t('Entity Types'), |
249 | '#options' => $this->entityTypes(), |
250 | '#default_value' => $config->get('counter.entity_types') ?? [], |
251 | '#description' => $this->t('Which entity types should be tracked.'), |
252 | ]; |
253 | |
254 | $form['retention'] = [ |
255 | '#type' => 'details', |
256 | '#title' => $this->t('Retention'), |
257 | '#group' => 'tracking_scope', |
258 | ]; |
259 | $form['retention']['flush_log_timer'] = [ |
260 | '#type' => 'select', |
261 | '#title' => $this->t('Discard visitors logs older than'), |
262 | '#default_value' => $config->get('flush_log_timer'), |
263 | '#options' => [ |
264 | 0 => $this->t('Never'), |
265 | 3600 => $this->t('1 hour'), |
266 | 10800 => $this->t('3 hours'), |
267 | 21600 => $this->t('6 hours'), |
268 | 32400 => $this->t('9 hours'), |
269 | 43200 => $this->t('12 hours'), |
270 | 86400 => $this->t('1 day'), |
271 | 172800 => $this->t('2 days'), |
272 | 259200 => $this->t('3 days'), |
273 | 604800 => $this->t('1 week'), |
274 | 1209600 => $this->t('2 weeks'), |
275 | 4838400 => $this->t('1 month 3 weeks'), |
276 | 9676800 => $this->t('3 months 3 weeks'), |
277 | 31536000 => $this->t('1 year'), |
278 | ], |
279 | '#description' => |
280 | $this->t('Older visitors log entries (including referrer statistics) will be automatically discarded. (Requires a correctly configured <a href="@cron">cron maintenance task</a>.)', |
281 | ['@cron' => Url::fromRoute('system.status')->toString()] |
282 | ), |
283 | ]; |
284 | |
285 | $form['retention']['bot_retention_log'] = [ |
286 | '#type' => 'select', |
287 | '#title' => $this->t('Discard bot logs older than'), |
288 | '#default_value' => $config->get('bot_retention_log'), |
289 | '#options' => [ |
290 | -1 => $this->t('Do not log'), |
291 | 0 => $this->t('Never'), |
292 | 3600 => $this->t('1 hour'), |
293 | 10800 => $this->t('3 hours'), |
294 | 21600 => $this->t('6 hours'), |
295 | 32400 => $this->t('9 hours'), |
296 | 43200 => $this->t('12 hours'), |
297 | 86400 => $this->t('1 day'), |
298 | 172800 => $this->t('2 days'), |
299 | 259200 => $this->t('3 days'), |
300 | 604800 => $this->t('1 week'), |
301 | 1209600 => $this->t('2 weeks'), |
302 | 4838400 => $this->t('1 month 3 weeks'), |
303 | 9676800 => $this->t('3 months 3 weeks'), |
304 | 31536000 => $this->t('1 year'), |
305 | ], |
306 | '#description' => |
307 | $this->t('Control how long or if visits by bots are logged.'), |
308 | ]; |
309 | |
310 | $form['miscellaneous'] = [ |
311 | '#type' => 'details', |
312 | '#title' => $this->t('Miscellaneous'), |
313 | '#group' => 'tracking_scope', |
314 | ]; |
315 | |
316 | $script_type = $config->get('script_type'); |
317 | $form['miscellaneous']['script_type'] = [ |
318 | '#type' => 'radios', |
319 | '#title' => $this->t('Script type'), |
320 | '#options' => [ |
321 | 'minified' => $this->t('Minified'), |
322 | 'full' => $this->t('Full'), |
323 | ], |
324 | '#default_value' => $script_type == 'full' ? 'full' : 'minified', |
325 | '#description' => $this->t('Full script is for debugging purposes. Minified script is for production.'), |
326 | ]; |
327 | $form['miscellaneous']['items_per_page'] = [ |
328 | '#type' => 'select', |
329 | '#title' => 'Items per page', |
330 | '#default_value' => $config->get('items_per_page'), |
331 | '#options' => [ |
332 | 5 => 5, |
333 | 10 => 10, |
334 | 25 => 25, |
335 | 50 => 50, |
336 | 100 => 100, |
337 | 200 => 200, |
338 | 250 => 250, |
339 | 500 => 500, |
340 | 1000 => 1000, |
341 | ], |
342 | '#description' => |
343 | $this->t('This is only used for the referrer report.'), |
344 | ]; |
345 | |
346 | return $form; |
347 | } |
348 | |
349 | /** |
350 | * {@inheritdoc} |
351 | */ |
352 | public function submitForm(array &$form, FormStateInterface $form_state) { |
353 | $config = $this->config(self::SETTINGS); |
354 | $values = $form_state->getValues(); |
355 | |
356 | $config |
357 | ->set('theme', $values['theme']) |
358 | ->set('items_per_page', $values['items_per_page']) |
359 | ->set('flush_log_timer', $values['flush_log_timer']) |
360 | ->set('bot_retention_log', $values['bot_retention_log']) |
361 | ->set('track.userid', $values['visitors_trackuserid']) |
362 | ->set('counter.enabled', $values['counter_enabled']) |
363 | ->set('counter.entity_types', array_filter($values['entity_types'] ?? [])) |
364 | ->set('disable_tracking', $values['visitors_disable_tracking']) |
365 | ->set('visibility.request_path_mode', $values['visitors_visibility_request_path_mode']) |
366 | ->set('visibility.request_path_pages', $values['visitors_visibility_request_path_pages']) |
367 | ->set('visibility.user_account_mode', $values['visitors_visibility_user_account_mode']) |
368 | ->set('visibility.user_role_mode', $values['visitors_visibility_user_role_mode']) |
369 | ->set('visibility.user_role_roles', array_filter($values['visitors_visibility_user_role_roles'])) |
370 | ->set('visibility.exclude_user1', $values['visibility_exclude_user1']) |
371 | ->set('script_type', $values['script_type'] ?? 'minified') |
372 | ->save(); |
373 | |
374 | parent::submitForm($form, $form_state); |
375 | } |
376 | |
377 | /** |
378 | * Returns a list of entity types. |
379 | */ |
380 | protected function entityTypes() { |
381 | $entity_types_list = []; |
382 | $entity_definitions = $this->entityTypeManager->getDefinitions(); |
383 | foreach ($entity_definitions as $entity_name => $entity_definition) { |
384 | if ($entity_definition instanceof ConfigEntityType) { |
385 | continue; |
386 | } |
387 | $entity_types_list[$entity_name] = (string) $entity_definition->getLabel(); |
388 | } |
389 | asort($entity_types_list); |
390 | |
391 | return $entity_types_list; |
392 | } |
393 | |
394 | /** |
395 | * Returns a list of roles. |
396 | */ |
397 | protected function roleOptions() { |
398 | $user_roles = $this->entityTypeManager->getStorage('user_role')->loadMultiple(); |
399 | $options = []; |
400 | foreach ($user_roles as $role) { |
401 | $options[$role->id()] = $role->label(); |
402 | } |
403 | |
404 | return \array_map('\Drupal\Component\Utility\Html::escape', $options); |
405 | } |
406 | |
407 | } |