Passed
Pull Request — 8.x-2.x (#58)
by Frédéric G.
03:34
created

Requirements::checkDatabaseAliasConsistency()   B

Complexity

Conditions 6
Paths 7

Size

Total Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
nc 7
nop 1
dl 0
loc 34
rs 8.7537
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace Drupal\mongodb_watchdog\Install;
6
7
use Drupal\Component\Serialization\SerializationInterface;
8
use Drupal\Core\Config\ConfigFactoryInterface;
9
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
10
use Drupal\Core\Messenger\MessengerInterface;
11
use Drupal\Core\Site\Settings;
12
use Drupal\Core\StringTranslation\StringTranslationTrait;
13
use Drupal\Core\Url;
14
use Drupal\mongodb\MongoDb;
15
use Drupal\mongodb_watchdog\Logger;
16
use Symfony\Component\DependencyInjection\ContainerInterface;
17
use Symfony\Component\HttpFoundation\RequestStack;
18
19
/**
20
 * Class Requirements implements hook_requirements().
21
 */
22
class Requirements implements ContainerInjectionInterface {
23
  use StringTranslationTrait;
24
25
  /**
26
   * The module configuration.
27
   *
28
   * @var \Drupal\Core\Config\Config
29
   */
30
  protected $config;
31
32
  /**
33
   * The config.factory service.
34
   *
35
   * @var \Drupal\Core\Config\ConfigFactoryInterface
36
   */
37
  protected $configFactory;
38
39
  /**
40
   * The messenger service.
41
   *
42
   * @var \Drupal\Core\Messenger\MessengerInterface
43
   */
44
  protected $messenger;
45
46
  /**
47
   * The request_stack service.
48
   *
49
   * @var \Symfony\Component\HttpFoundation\RequestStack
50
   */
51
  protected $requestStack;
52
53
  /**
54
   * The serialization.yaml service.
55
   *
56
   * @var \Drupal\Component\Serialization\SerializationInterface
57
   */
58
  protected $serialization;
59
60
  /**
61
   * The section of Settings related to the MongoDB package.
62
   *
63
   * @var array
64
   */
65
  protected $settings;
66
67
  /**
68
   * Requirements constructor.
69
   *
70
   * @param \Drupal\Core\Site\Settings $settings
71
   *   The settings service.
72
   * @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
73
   *   The config.factory service.
74
   * @param \Symfony\Component\HttpFoundation\RequestStack $requestStack
75
   *   The request_stack service.
76
   * @param \Drupal\Component\Serialization\SerializationInterface $serialization
77
   *   The serialization.yaml service.
78
   * @param \Drupal\Core\Messenger\MessengerInterface $messenger
79
   *   The messenger service.
80
   */
81
  public function __construct(
82
    Settings $settings,
83
    ConfigFactoryInterface $configFactory,
84
    RequestStack $requestStack,
85
    SerializationInterface $serialization,
86
    MessengerInterface $messenger
87
  ) {
88
    $this->serialization = $serialization;
89
    $this->configFactory = $configFactory;
90
    $this->requestStack = $requestStack;
91
    $this->settings = $settings->get(MongoDb::MODULE);
92
    $this->messenger = $messenger;
93
  }
94
95
  /**
96
   * {@inheritdoc}
97
   */
98
  public static function create(ContainerInterface $container): self {
99
    return new static(
100
      $container->get('settings'),
101
      $container->get('config.factory'),
102
      $container->get('request_stack'),
103
      $container->get('serialization.yaml'),
104
      $container->get('messenger'));
105
  }
106
107
  /**
108
   * Apply database aliases consistency checks.
109
   *
110
   * @param array $state
111
   *   The current state of requirements checks.
112
   *
113
   * @return array
114
   *   - array: The current state of requirements checks.
115
   *   - bool: true if the checks added an error, false otherwise
116
   */
117
  protected function checkDatabaseAliasConsistency(array $state) : array {
118
    $databases = $this->settings['databases'];
119
    if (!isset($databases[Logger::DB_LOGGER])) {
120
      $state[Logger::MODULE] += [
121
        'severity' => REQUIREMENT_ERROR,
122
        'value' => $this->t('Missing `@alias` database alias in settings.',
123
          ['@alias' => Logger::DB_LOGGER]),
124
      ];
125
      return [$state, TRUE];
126
    }
127
128
    [$loggerClient, $loggerDb] = $databases[Logger::DB_LOGGER];
0 ignored issues
show
Bug introduced by
The variable $loggerClient does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $loggerDb does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
129
    unset($databases[Logger::DB_LOGGER]);
130
    $duplicates = [];
131
    foreach ($databases as $alias => $list) {
132
      [$client, $database] = $list;
0 ignored issues
show
Bug introduced by
The variable $client does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $database does not exist. Did you mean $databases?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
133
      if ($loggerClient == $client && $loggerDb == $database) {
0 ignored issues
show
Bug introduced by
The variable $database does not exist. Did you mean $databases?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
134
        $duplicates[] = "`$alias`";
135
      }
136
    }
137
    if (!empty($duplicates)) {
138
      $state[Logger::MODULE] += [
139
        'severity' => REQUIREMENT_ERROR,
140
        'value' => $this->t('The `@alias` alias points to the same database as @others.', [
141
          '@alias' => Logger::DB_LOGGER,
142
          '@others' => implode(', ', $duplicates),
143
        ]),
144
        'description' => $this->t('Those databases would also be dropped when uninstalling the watchdog module.'),
145
      ];
146
      return [$state, TRUE];
147
    }
148
149
    return [$state, FALSE];
150
  }
151
152
  /**
153
   * Load the configuration from default or from active configuration.
154
   *
155
   * @param bool $useDefault
156
   *   Use default configuration ?
157
   */
158
  protected function loadConfig(bool $useDefault): void {
159
    if ($useDefault) {
160
      $rawDefaultConfig = file_get_contents(__DIR__ . '/../../config/install/mongodb_watchdog.settings.yml');
161
      $defaultConfigData = $this->serialization->decode($rawDefaultConfig);
162
      $this->config = $this->configFactory->getEditable(Logger::MODULE);
163
      $this->config->initWithData($defaultConfigData);
164
      return;
165
    }
166
167
    $this->config = $this->configFactory->get(Logger::CONFIG_NAME);
168
  }
169
170
  /**
171
   * Check the consistency of request tracking vs configuration and environment.
172
   *
173
   * @param array $state
174
   *   The current state of requirements.
175
   *
176
   * @return array
177
   *   - array: The current state of requirements checks.
178
   *   - bool: true if the checks added an error, false otherwise
179
   */
180
  protected function checkRequestTracking(array $state) : array {
181
    $requestTracking = $this->config->get('request_tracking');
182
    if ($this->hasUniqueId()) {
183
      $state[Logger::MODULE] += $requestTracking
184
        ? [
185
          'value' => $this->t('Mod_unique_id available and used'),
186
          'severity' => REQUIREMENT_OK,
187
          'description' => $this->t('Request tracking is available and active.'),
188
        ]
189
        : [
190
          'value' => $this->t('Unused mod_unique_id'),
191
          'severity' => REQUIREMENT_INFO,
192
          'description' => $this->t('The site could track requests, but request tracking is not enabled. You could disable mod_unique_id to save resources, or enable request tracking</a> for a better logging experience.'),
193
        ];
194
195
      return [$state, FALSE];
196
    }
197
198
    $state[Logger::MODULE] += [
199
      'value' => $this->t('No mod_unique_id'),
200
    ];
201
    if ($requestTracking) {
202
      if (php_sapi_name() === 'cli') {
203
        $message = $this->t('Request tracking is configured, but the site cannot check the working mod_unique_id configuration from the CLI. Be sure to validate configuration on the <a href=":report">status page</a>.', [
204
          ':report' => Url::fromRoute('system.status')->toString(),
205
        ]);
206
        $state[Logger::MODULE] += [
207
          'severity' => REQUIREMENT_WARNING,
208
          'description' => $message,
209
        ];
210
        $this->messenger->addWarning($message);
211
        return [$state, FALSE];
212
      }
213
214
      $state[Logger::MODULE] += [
215
        'severity' => REQUIREMENT_ERROR,
216
        'description' => $this->t('Request tracking is configured, but the site is not served by Apache with a working mod_unique_id.'),
217
      ];
218
      return [$state, TRUE];
219
    }
220
221
    $state[Logger::MODULE] += [
222
      'severity' => REQUIREMENT_OK,
223
      'description' => $this->t('Request tracking is not configured.'),
224
    ];
225
    return [$state, FALSE];
226
  }
227
228
  /**
229
   * Implements hook_requirements().
230
   */
231
  public function check(string $phase): array {
232
    $state = [
233
      Logger::MODULE => [
234
        'title' => 'MongoDB watchdog',
235
      ],
236
    ];
237
238
    [$state, $err] = $this->checkDatabaseAliasConsistency($state);
0 ignored issues
show
Bug introduced by
The variable $err does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
239
    if ($err) {
240
      return $state;
241
    }
242
243
    $this->loadConfig($phase !== 'runtime');
244
245
    [$state, $err] = $this->checkRequestTracking($state);
246
    if ($err) {
247
      return $state;
248
    }
249
250
    return $state;
251
  }
252
253
  /**
254
   * Is mod_unique_id available on this instance ?
255
   *
256
   * @return bool
257
   *   Is it ?
258
   */
259
  protected function hasUniqueId(): bool {
260
    $server = $this->requestStack->getCurrentRequest()->server;
261
    return $server->has('UNIQUE_ID') || $server->has('REDIRECT_UNIQUE_ID');
262
  }
263
264
}
265