Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
279 / 279
100.00% covered (success)
100.00%
4 / 4
CRAP
n/a
0 / 0
visitors_install
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
3
visitors_schema
100.00% covered (success)
100.00%
213 / 213
100.00% covered (success)
100.00%
1 / 1
1
visitors_requirements
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
3
visitors_update_30000
100.00% covered (success)
100.00%
41 / 41
100.00% covered (success)
100.00%
1 / 1
9
1<?php
2
3/**
4 * @file
5 * Install/uninstall visitors module.
6 */
7
8use Drupal\Component\Serialization\Yaml;
9use Drupal\Core\Entity\EntityTypeInterface;
10use Drupal\Core\Url;
11
12/**
13 * Implements hook_install().
14 */
15function visitors_install($is_syncing) {
16  if ($is_syncing) {
17    return;
18  }
19  if (!\Drupal::moduleHandler()->moduleExists('statistics')) {
20    return;
21  }
22  $settings = \Drupal::service('config.factory')->getEditable('visitors.settings');
23  $settings->set('counter.enabled', FALSE)
24    ->save();
25
26  \Drupal::messenger()->addWarning(t(
27    'The Statistics module is installed. <a href="@url">Convert the Statistics node views</a> to Visitors page views.',
28    ['@url' => Url::fromRoute('visitors.statistics_migrate')->toString()]
29  ));
30
31}
32
33/**
34 * Implements hook_schema().
35 */
36function visitors_schema() {
37
38  $schema['visitors_visit'] = [
39    'fields' => [
40      'id' => [
41        'description' => 'Primary key',
42        'type' => 'serial',
43        'not null' => TRUE,
44      ],
45      'visitor_id' => [
46        'description' => 'Unique id, provided by the visitor',
47        'type' => 'varchar',
48        'length' => 32,
49        'not null' => FALSE,
50        'default' => NULL,
51      ],
52      'uid' => [
53        'description' => 'The user of the session',
54        'type' => 'int',
55        'not null' => FALSE,
56      ],
57      'localtime' => [
58        'description' => 'Seconds since midnight, in the local of the visitor',
59        'type' => 'int',
60        'size' => 'medium',
61        'not null' => FALSE,
62        'default' => NULL,
63      ],
64      'returning' => [
65        'description' => 'Is the visitor returning, or new',
66        'type' => 'int',
67        'size' => 'tiny',
68      ],
69      'total_visits' => [
70        'description' => 'Total visits',
71        'type' => 'int',
72        'not null' => TRUE,
73        'default' => 0,
74      ],
75      'total_page_views' => [
76        'description' => 'Total page views this visit',
77        'type' => 'int',
78        'not null' => TRUE,
79        'default' => 0,
80      ],
81      'total_events' => [
82        'description' => 'Total events this visit',
83        'type' => 'int',
84        'not null' => TRUE,
85        'default' => 0,
86      ],
87      'entry' => [
88        'description' => 'First page view',
89        'type' => 'int',
90        'not null' => FALSE,
91        'default' => NULL,
92      ],
93      'entry_time' => [
94        'description' => 'The time the visit was started',
95        'type' => 'int',
96        'not null' => FALSE,
97        'default' => NULL,
98      ],
99      'exit' => [
100        'description' => 'Last page view',
101        'type' => 'int',
102        'not null' => FALSE,
103        'default' => NULL,
104      ],
105      'exit_time' => [
106        'description' => 'The time the visit was ended',
107        'type' => 'int',
108        'not null' => FALSE,
109        'default' => NULL,
110      ],
111      'total_time' => [
112        'description' => 'The total time of the visit',
113        'type' => 'int',
114        'not null' => FALSE,
115        'default' => NULL,
116      ],
117      'time_since_first' => [
118        'description' => 'Seconds since the visitor\'s first visit',
119        'type' => 'int',
120        'not null' => FALSE,
121        'default' => NULL,
122      ],
123      'time_since_last' => [
124        'description' => 'Seconds since the visitor\'s last visit',
125        'type' => 'int',
126        'not null' => FALSE,
127        'default' => NULL,
128      ],
129      'bot' => [
130        'description' => 'Is the visitor a bot',
131        'type' => 'int',
132        'size' => 'tiny',
133        'not null' => FALSE,
134        'default' => NULL,
135      ],
136      'config_id' => [
137        'description' => 'The fingerprint id',
138        'type' => 'varchar',
139        'length' => 16,
140        'not null' => TRUE,
141      ],
142      'config_resolution' => [
143        'description' => 'The screen resolution',
144        'type' => 'varchar',
145        'length' => 18,
146        'not null' => FALSE,
147        'default' => NULL,
148      ],
149      'config_pdf' => [
150        'description' => 'Has PDF support',
151        'type' => 'int',
152        'size' => 'tiny',
153        'not null' => FALSE,
154        'default' => NULL,
155      ],
156      'config_flash' => [
157        'description' => 'Has Flash support',
158        'type' => 'int',
159        'size' => 'tiny',
160        'not null' => FALSE,
161        'default' => NULL,
162      ],
163      'config_java' => [
164        'description' => 'Has Java support',
165        'type' => 'int',
166        'size' => 'tiny',
167        'not null' => FALSE,
168        'default' => NULL,
169      ],
170      'config_quicktime' => [
171        'description' => 'Has Quicktime support',
172        'type' => 'int',
173        'size' => 'tiny',
174        'not null' => FALSE,
175        'default' => NULL,
176      ],
177      'config_realplayer' => [
178        'description' => 'Has Realplayer support',
179        'type' => 'int',
180        'size' => 'tiny',
181        'not null' => FALSE,
182        'default' => NULL,
183      ],
184      'config_windowsmedia' => [
185        'description' => 'Has Windows Media support',
186        'type' => 'int',
187        'size' => 'tiny',
188        'not null' => FALSE,
189        'default' => NULL,
190      ],
191      'config_silverlight' => [
192        'description' => 'Has Silverlight support',
193        'type' => 'int',
194        'size' => 'tiny',
195        'not null' => FALSE,
196        'default' => NULL,
197      ],
198      'config_cookie' => [
199        'description' => 'Has cookie support',
200        'type' => 'int',
201        'size' => 'tiny',
202        'not null' => FALSE,
203        'default' => NULL,
204      ],
205      'config_browser_engine' => [
206        'description' => 'The browser engine',
207        'type' => 'varchar',
208        'length' => '10',
209        'not null' => FALSE,
210        'default' => NULL,
211      ],
212      'config_browser_name' => [
213        'description' => 'The browser name',
214        'type' => 'varchar',
215        'length' => '2',
216        'not null' => FALSE,
217        'default' => NULL,
218      ],
219      'config_browser_version' => [
220        'description' => 'The browser version',
221        'type' => 'varchar',
222        'length' => '20',
223        'not null' => FALSE,
224        'default' => NULL,
225      ],
226      'config_client_type' => [
227        'description' => 'The client type',
228        'type' => 'varchar',
229        'length' => '100',
230        'not null' => FALSE,
231        'default' => NULL,
232      ],
233      'config_device_brand' => [
234        'description' => 'The device brand',
235        'type' => 'varchar',
236        'length' => '100',
237        'not null' => FALSE,
238        'default' => NULL,
239      ],
240      'config_device_model' => [
241        'description' => 'The device model',
242        'type' => 'varchar',
243        'length' => '100',
244        'not null' => FALSE,
245        'default' => NULL,
246      ],
247      'config_device_type' => [
248        'description' => 'The device type',
249        'type' => 'varchar',
250        'length' => '100',
251        'not null' => FALSE,
252        'default' => NULL,
253      ],
254      'config_os' => [
255        'description' => 'The operating system',
256        'type' => 'varchar',
257        'length' => '3',
258        'not null' => FALSE,
259        'default' => NULL,
260      ],
261      'config_os_version' => [
262        'description' => 'The operating system version',
263        'type' => 'varchar',
264        'length' => '100',
265        'not null' => FALSE,
266        'default' => NULL,
267      ],
268      'location_browser_lang' => [
269        'description' => 'The browser language',
270        'type' => 'varchar',
271        'length' => 20,
272        'not null' => FALSE,
273        'default' => NULL,
274      ],
275      'location_ip' => [
276        'description' => 'The IP address',
277        'type' => 'varchar',
278        'length' => 45,
279        'not null' => TRUE,
280        'default' => '',
281      ],
282      'location_continent' => [
283        'description' => 'The continent of the visitor',
284        'type' => 'varchar',
285        'length' => 2,
286        'not null' => FALSE,
287        'default' => '',
288      ],
289      'location_country' => [
290        'description' => 'The country of the visitor',
291        'type' => 'varchar',
292        'length' => 2,
293        'not null' => FALSE,
294        'default' => '',
295      ],
296      'location_region' => [
297        'description' => 'The region of the visitor',
298        'type' => 'varchar',
299        'length' => 128,
300        'not null' => FALSE,
301        'default' => '',
302      ],
303      'location_city' => [
304        'description' => 'The city of the visitor',
305        'type' => 'varchar',
306        'length' => 128,
307        'not null' => FALSE,
308        'default' => '',
309      ],
310      'location_latitude' => [
311        'description' => 'The latitude from the IP address',
312        'type' => 'numeric',
313        'precision' => 13,
314        'scale' => 10,
315        'default' => NULL,
316      ],
317      'location_longitude' => [
318        'description' => 'The longitude from the IP address',
319        'type' => 'numeric',
320        'precision' => 13,
321        'scale' => 10,
322        'default' => NULL,
323      ],
324      'referer_keyword' => [
325        'description' => 'The referer keyword',
326        'type' => 'varchar',
327        'length' => 255,
328        'not null' => FALSE,
329        'default' => NULL,
330      ],
331      'referer_name' => [
332        'description' => 'The referer name',
333        'type' => 'varchar',
334        'length' => 255,
335        'not null' => FALSE,
336        'default' => NULL,
337      ],
338      'referer_type' => [
339        'description' => 'The referer type',
340        'type' => 'varchar',
341        'length' => 32,
342        'not null' => FALSE,
343        'default' => NULL,
344      ],
345      'referer_url' => [
346        'description' => 'The referer URL',
347        'type' => 'varchar',
348        'length' => 1500,
349        'not null' => FALSE,
350        'default' => NULL,
351      ],
352    ],
353    'primary key' => ['id'],
354    'indexes' => [
355      'visitor_id' => ['visitor_id'],
356      'bot' => ['bot'],
357      'exit_time' => ['exit_time'],
358      'uid' => ['uid'],
359    ],
360  ];
361
362  $schema['visitors_event'] = [
363    'fields' => [
364      'id' => [
365        'description' => 'Primary key',
366        'type' => 'serial',
367        'not null' => TRUE,
368      ],
369      'visit_id' => [
370        'description' => 'The visitors_visit id',
371        'type' => 'int',
372      ],
373      'page_view' => [
374        'description' => 'The unique page view id',
375        'type' => 'varchar',
376        'length' => 32,
377        'not null' => FALSE,
378        'default' => NULL,
379      ],
380      'plugin' => [
381        'description' => 'The plugin that generated the event',
382        'type' => 'varchar',
383        'length' => 255,
384        'not null' => FALSE,
385        'default' => NULL,
386      ],
387      'event' => [
388        'description' => 'The event',
389        'type' => 'varchar',
390        'length' => 255,
391        'not null' => FALSE,
392        'default' => NULL,
393      ],
394      'plugin_int_1' => [
395        'description' => 'The first event int variable',
396        'type' => 'int',
397        'not null' => FALSE,
398        'default' => NULL,
399      ],
400      'plugin_int_2' => [
401        'description' => 'The second event int variable',
402        'type' => 'int',
403        'not null' => FALSE,
404        'default' => NULL,
405      ],
406      'plugin_var_1' => [
407        'description' => 'The first event varchar variable',
408        'type' => 'varchar',
409        'length' => 255,
410        'not null' => FALSE,
411        'default' => NULL,
412      ],
413      'plugin_var_2' => [
414        'description' => 'The second event varchar variable',
415        'type' => 'varchar',
416        'length' => 255,
417        'not null' => FALSE,
418        'default' => NULL,
419      ],
420      'plugin_var_3' => [
421        'description' => 'The third event varchar variable',
422        'type' => 'varchar',
423        'length' => 255,
424        'not null' => FALSE,
425        'default' => NULL,
426      ],
427      'plugin_var_4' => [
428        'description' => 'The fourth event varchar variable',
429        'type' => 'varchar',
430        'length' => 255,
431        'not null' => FALSE,
432        'default' => NULL,
433      ],
434      'title' => [
435        'description' => 'The page title',
436        'type' => 'text',
437        'not null' => TRUE,
438      ],
439      'uid' => [
440        'description' => 'The user who viewed the page',
441        'type' => 'int',
442      ],
443      'url_prefix' => [
444        'description' => 'The protocol and if started with www',
445        'type' => 'int',
446        'size' => 'small',
447      ],
448      'url' => [
449        'description' => 'The page URL',
450        'type' => 'text',
451        'not null' => TRUE,
452      ],
453      'path' => [
454        'description' => 'The Drupal path',
455        'type' => 'varchar',
456        'length' => 255,
457        'not null' => TRUE,
458        'default' => '',
459      ],
460      'route' => [
461        'description' => 'The Drupal route name',
462        'type' => 'varchar',
463        'length' => 255,
464        'not null' => TRUE,
465        'default' => '',
466      ],
467      'referrer_url' => [
468        'description' => 'The referrer URL',
469        'type' => 'text',
470        'not null' => TRUE,
471      ],
472      'server' => [
473        'description' => 'The server that generated the response',
474        'type' => 'varchar',
475        'length' => 255,
476        'not null' => FALSE,
477        'default' => NULL,
478      ],
479      'pf_network' => [
480        'description' => 'Network performance',
481        'type' => 'int',
482        'not null' => FALSE,
483        'default' => NULL,
484      ],
485      'pf_server' => [
486        'description' => 'Server performance',
487        'type' => 'int',
488        'not null' => FALSE,
489        'default' => NULL,
490      ],
491      'pf_transfer' => [
492        'description' => 'Transfer performance',
493        'type' => 'int',
494        'not null' => FALSE,
495        'default' => NULL,
496      ],
497      'pf_dom_processing' => [
498        'description' => 'DOM processing performance',
499        'type' => 'int',
500        'not null' => FALSE,
501        'default' => NULL,
502      ],
503      'pf_dom_complete' => [
504        'description' => 'DOM complete performance',
505        'type' => 'int',
506        'not null' => FALSE,
507        'default' => NULL,
508      ],
509      'pf_on_load' => [
510        'description' => 'On load performance',
511        'type' => 'int',
512        'not null' => FALSE,
513        'default' => NULL,
514      ],
515      'pf_total' => [
516        'description' => 'Total performance',
517        'type' => 'int',
518        'not null' => FALSE,
519        'default' => NULL,
520      ],
521      'created' => [
522        'description' => 'The time the request was made',
523        'type' => 'int',
524      ],
525    ],
526    'primary key' => ['id'],
527    'indexes' => [
528      'visit_id' => ['visit_id'],
529      'created' => ['created'],
530    ],
531  ];
532
533  $schema['visitors_counter'] = [
534    'fields' => [
535      'entity_id' => [
536        'description' => 'The entity id for these visits.',
537        'type' => 'int',
538        'unsigned' => TRUE,
539        'not null' => TRUE,
540        'default' => 0,
541      ],
542      'entity_type' => [
543        'type' => 'varchar_ascii',
544        'not null' => TRUE,
545        'default' => 'node',
546        'length' => EntityTypeInterface::ID_MAX_LENGTH,
547        'description' => 'The entity_type of the entity for these visits.',
548      ],
549      'total' => [
550        'description' => 'The total number of times the entity has been viewed.',
551        'type' => 'int',
552        'unsigned' => TRUE,
553        'not null' => TRUE,
554        'default' => 0,
555        'size' => 'big',
556      ],
557      'today' => [
558        'description' => 'The total number of times the entity has been viewed today.',
559        'type' => 'int',
560        'unsigned' => TRUE,
561        'not null' => TRUE,
562        'default' => 0,
563        'size' => 'medium',
564      ],
565      'timestamp' => [
566        'description' => 'The most recent time the entity has been viewed.',
567        'type' => 'int',
568        'unsigned' => TRUE,
569        'not null' => TRUE,
570        'default' => 0,
571      ],
572    ],
573    'primary key' => ['entity_type', 'entity_id'],
574  ];
575
576  return $schema;
577}
578
579/**
580 * Implements hook_requirements().
581 */
582function visitors_requirements($phase) {
583  $requirements = [];
584  if ($phase != 'runtime') {
585    return $requirements;
586  }
587  $device = \Drupal::service('visitors.device');
588  if (!$device->hasLibrary()) {
589    $requirements['visitors_device'] = [
590      'title' => t('Device Detector'),
591      'value' => t('Not found'),
592      'severity' => REQUIREMENT_WARNING,
593      'description' => t('The <a href=":url">Device Detector</a> library is strongly encouraged by the Visitors module. Composer will download the library automatically.', [
594        ':url' => 'https://github.com/matomo-org/device-detector',
595      ]),
596    ];
597  }
598
599  return $requirements;
600}
601
602/**
603 * Upgrade to Visitors 3.
604 */
605function visitors_update_30000(&$sandbox) {
606
607  if (!isset($sandbox['current'])) {
608    $sandbox['current'] = 0;
609    $sandbox['max'] = 4;
610  }
611
612  // Change visitors.settings to visitors.settings.
613  if ($sandbox['current'] == 0) {
614    $config_factory = \Drupal::configFactory();
615
616    $config = $config_factory->getEditable('visitors.config');
617    $config_data = $config->getRawData();
618
619    $settings = $config_factory->getEditable('visitors.settings');
620    $settings->setData($config_data)->save();
621
622    $config->delete();
623  }
624
625  if ($sandbox['current'] == 1) {
626    $schema = \Drupal::database()->schema();
627    // @todo replace visitors_schema() with static before an initial release.
628    $visitors_schema = visitors_schema();
629    $schema->createTable('visitors_visit', $visitors_schema['visitors_visit']);
630    $schema->createTable('visitors_event', $visitors_schema['visitors_event']);
631  }
632
633  if ($sandbox['current'] == 2) {
634    $config_factory = \Drupal::configFactory();
635
636    // @todo This needs to be replace with static before an initial release.
637    $view = file_get_contents(__DIR__ . '/config/optional/views.view.visitors.yml');
638    $config_data = Yaml::decode($view);
639    $config_factory->getEditable('views.view.visitors')->setData($config_data)->save();
640
641    // @todo This needs to be replace with static before an initial release.
642    $spam = file_get_contents(__DIR__ . '/config/install/visitors.spam.yml');
643    $config_data = Yaml::decode($spam);
644    $config_factory->getEditable('visitors.spam')->setData($config_data)->save();
645
646    // @todo This needs to be replace with static before an initial release.
647    $ai_assistants = file_get_contents(__DIR__ . '/config/install/visitors.ai_assistants.yml');
648    $config_data = Yaml::decode($ai_assistants);
649    $config_factory->getEditable('visitors.ai_assistants')->setData($config_data)->save();
650
651    // @todo This needs to be replace with static before an initial release.
652    $search_engine = file_get_contents(__DIR__ . '/config/install/visitors.search_engines.yml');
653    $config_data = Yaml::decode($search_engine);
654    $config_factory->getEditable('visitors.search_engine')->setData($config_data)->save();
655
656    // @todo This needs to be replace with static before an initial release.
657    $social_networks = file_get_contents(__DIR__ . '/config/install/visitors.social_networks.yml');
658    $config_data = Yaml::decode($social_networks);
659    $config_factory->getEditable('visitors.social_networks')->setData($config_data)->save();
660
661    // Check if views 'views.view.visitors_geoip' exists, and delete it.
662    $geoip_view = $config_factory->getEditable('views.view.visitors_geoip');
663    if ($geoip_view) {
664      $geoip_view->delete();
665    }
666
667  }
668
669  if ($sandbox['current'] == 3) {
670    $visitors_geoip_is_installed = \Drupal::moduleHandler()->moduleExists('visitors_geoip');
671    if ($visitors_geoip_is_installed) {
672      \Drupal::service('module_installer')->uninstall(['visitors_geoip']);
673    }
674  }
675
676  $sandbox['current'] += 1;
677
678  $sandbox['#finished'] = ($sandbox['max'] == $sandbox['current']) ? 1 : $sandbox['current'] / $sandbox['max'];
679}