Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
38 / 38
100.00% covered (success)
100.00%
5 / 5
CRAP
100.00% covered (success)
100.00%
1 / 1
PageAttachmentsService
100.00% covered (success)
100.00%
38 / 38
100.00% covered (success)
100.00%
5 / 5
13
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
 pageAttachments
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
3
 attachMetaData
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
1
 attachToolbar
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 attachEntityCounter
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
6
1<?php
2
3declare(strict_types=1);
4
5namespace Drupal\visitors\Service;
6
7use Drupal\Core\Access\AccessResult;
8use Drupal\Core\Config\ConfigFactoryInterface;
9use Drupal\Core\Extension\ModuleHandlerInterface;
10use Drupal\Core\Routing\RouteMatchInterface;
11use Drupal\Core\Session\AccountInterface;
12use Drupal\Core\Utility\Error;
13use Drupal\visitors\VisitorsPageAttachmentsInterface;
14use Drupal\visitors\VisitorsVisibilityInterface;
15use Psr\Log\LoggerInterface;
16use Symfony\Component\HttpFoundation\RequestStack;
17
18/**
19 * Visitors Page Attachments Service.
20 */
21class PageAttachmentsService implements VisitorsPageAttachmentsInterface {
22
23  /**
24   * The config factory.
25   *
26   * @var \Drupal\Core\Config\ConfigFactoryInterface
27   */
28  protected $configFactory;
29
30  /**
31   * The current user service.
32   *
33   * @var \Drupal\Core\Session\AccountInterface
34   */
35  protected $currentUser;
36
37  /**
38   * The module handler service.
39   *
40   * @var \Drupal\Core\Extension\ModuleHandlerInterface
41   */
42  protected $moduleHandler;
43
44  /**
45   * The route match service.
46   *
47   * @var \Drupal\Core\Routing\ResettableStackedRouteMatchInterface
48   */
49  protected $routeMatch;
50
51  /**
52   * The request stack service.
53   *
54   * @var \Symfony\Component\HttpFoundation\RequestStack
55   */
56  protected $requestStack;
57
58  /**
59   * The visitors visibility service.
60   *
61   * @var \Drupal\visitors\VisitorsVisibilityInterface
62   */
63  protected $visibilityService;
64
65  /**
66   * The logger service.
67   *
68   * @var \Psr\Log\LoggerInterface
69   */
70  protected $logger;
71
72  /**
73   * Constructs a new Page Attachments Service.
74   *
75   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
76   *   The config factory.
77   * @param \Drupal\Core\Session\AccountInterface $current_user
78   *   The current user service.
79   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
80   *   The module handler service.
81   * @param \Drupal\Core\Routing\ResettableStackedRouteMatchInterface $route_match
82   *   The route match service.
83   * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
84   *   The request stack service.
85   * @param \Drupal\visitors\VisitorsVisibilityInterface $visibility_service
86   *   The visitors visibility service.
87   * @param \Psr\Log\LoggerInterface $logger
88   *   The logger service.
89   */
90  public function __construct(
91    ConfigFactoryInterface $config_factory,
92    AccountInterface $current_user,
93    ModuleHandlerInterface $module_handler,
94    RouteMatchInterface $route_match,
95    RequestStack $request_stack,
96    VisitorsVisibilityInterface $visibility_service,
97    LoggerInterface $logger,
98  ) {
99    $this->configFactory = $config_factory;
100    $this->currentUser = $current_user;
101    $this->moduleHandler = $module_handler;
102    $this->routeMatch = $route_match;
103    $this->requestStack = $request_stack;
104    $this->visibilityService = $visibility_service;
105    $this->logger = $logger;
106  }
107
108  /**
109   * {@inheritdoc}
110   */
111  public function pageAttachments(array &$page) {
112
113    $page['#cache']['tags'][] = 'user:' . $this->currentUser->id();
114    $page['#cache']['contexts'][] = 'user';
115    $page['#cache']['tags'][] = 'config:visitors.settings';
116
117    $this->attachToolbar($page);
118
119    try {
120      if ($this->visibilityService->isVisible()) {
121        $this->attachMetaData($page);
122        $this->attachEntityCounter($page);
123      }
124    }
125    catch (\Exception $e) {
126      Error::logException($this->logger, $e);
127    }
128  }
129
130  /**
131   * Attach meta data to the page.
132   *
133   * @param array $page
134   *   The page attachments array.
135   */
136  protected function attachMetaData(array &$page): void {
137    $route = $this->routeMatch->getRouteName();
138    $request = $this->requestStack->getCurrentRequest();
139    $base_path = $request->getBasePath();
140    $module_path = $this->moduleHandler->getModule('visitors')->getPath();
141
142    $page['#attached']['drupalSettings']['visitors']['module'] = "$base_path/$module_path";
143    $page['#attached']['drupalSettings']['visitors']['route'] = $route;
144    $page['#attached']['drupalSettings']['visitors']['server'] = gethostname();
145    $page['#attached']['library'][] = 'visitors/visitors';
146
147  }
148
149  /**
150   * Visitors toolbar integration.
151   *
152   * @param array $page
153   *   The page attachments array.
154   */
155  protected function attachToolbar(array &$page): void {
156    $required_permissions = ['access visitors', 'access toolbar'];
157
158    $access = AccessResult::allowedIfHasPermissions($this->currentUser, $required_permissions);
159    if ($access->isAllowed()) {
160      $page['#attached']['library'][] = 'visitors/menu';
161    }
162  }
163
164  /**
165   * Attach entity counter to the page.
166   *
167   * @param array $page
168   *   The page attachments array.
169   */
170  protected function attachEntityCounter(array &$page): void {
171    $route = $this->routeMatch->getRouteName();
172
173    $route_array = explode('.', $route);
174    if (count($route_array) == 3 && $route_array[0] == 'entity' && $route_array[2] == 'canonical') {
175      $entity_type = $route_array[1];
176
177      $settings = $this->configFactory->get('visitors.config');
178      $entity_types = $settings->get('counter.entity_types') ?? [];
179      if (!$settings->get('counter.enabled') || !in_array($entity_type, $entity_types)) {
180        return;
181      }
182
183      $entity_id = $this->routeMatch->getParameter($entity_type)->id();
184      $page['#attached']['drupalSettings']['visitors']['counter'] = "$entity_type:$entity_id";
185    }
186  }
187
188}