RequestController::buildMainTableRows()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 27
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 18
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 27
rs 9.6666
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Drupal\mongodb_watchdog\Controller;
6
7
use Drupal\Core\Config\ImmutableConfig;
0 ignored issues
show
Bug introduced by
The type Drupal\Core\Config\ImmutableConfig was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
8
use Drupal\Core\Datetime\DateFormatterInterface;
0 ignored issues
show
Bug introduced by
The type Drupal\Core\Datetime\DateFormatterInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
9
use Drupal\Core\Link;
0 ignored issues
show
Bug introduced by
The type Drupal\Core\Link was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
10
use Drupal\Core\Logger\RfcLogLevel;
0 ignored issues
show
Bug introduced by
The type Drupal\Core\Logger\RfcLogLevel was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
11
use Drupal\Core\Pager\PagerManagerInterface;
0 ignored issues
show
Bug introduced by
The type Drupal\Core\Pager\PagerManagerInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
12
use Drupal\mongodb_watchdog\Event;
13
use Drupal\mongodb_watchdog\Logger;
14
use Psr\Log\LoggerInterface;
0 ignored issues
show
Bug introduced by
The type Psr\Log\LoggerInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
15
use Symfony\Component\DependencyInjection\ContainerInterface;
0 ignored issues
show
Bug introduced by
The type Symfony\Component\Depend...tion\ContainerInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
16
use Symfony\Component\HttpFoundation\Request;
0 ignored issues
show
Bug introduced by
The type Symfony\Component\HttpFoundation\Request was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
17
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
0 ignored issues
show
Bug introduced by
The type Symfony\Component\HttpKe...n\NotFoundHttpException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
18
19
/**
20
 * The controller for the request events page.
21
 */
22
class RequestController extends ControllerBase {
23
24
  /**
25
   * The core date.formatter service.
26
   *
27
   * @var \Drupal\Core\Datetime\DateFormatterInterface
28
   */
29
  protected $dateFormatter;
30
31
  /**
32
   * A RfcLogLevel instance, to avoid static access.
33
   *
34
   * @var \Drupal\Core\Logger\RfcLogLevel
35
   */
36
  protected $rfcLogLevel;
37
38
  /**
39
   * The length of the absolute path to the site root, in runes.
40
   *
41
   * @var int
42
   */
43
  protected int $rootLength;
44
45
  /**
46
   * Controller constructor.
47
   *
48
   * @param \Psr\Log\LoggerInterface $logger
49
   *   The logger service, to log intervening events.
50
   * @param \Drupal\mongodb_watchdog\Logger $watchdog
51
   *   The MongoDB logger, to load stored events.
52
   * @param \Drupal\Core\Config\ImmutableConfig $config
53
   *   The module configuration.
54
   * @param \Drupal\Core\Datetime\DateFormatterInterface $dateFormatter
55
   *   The core date.formatter service.
56
   * @param \Drupal\Core\Pager\PagerManagerInterface $pagerManager
57
   *   The core pager.manager service.
58
   * @param \Drupal\Core\Logger\RfcLogLevel $rfcLogLevel
59
   *   A RfcLogLevel instance, to avoid static access.
60
   */
61
  public function __construct(
62
    LoggerInterface $logger,
63
    Logger $watchdog,
64
    ImmutableConfig $config,
65
    DateFormatterInterface $dateFormatter,
66
    PagerManagerInterface $pagerManager,
67
    RfcLogLevel $rfcLogLevel) {
68
    parent::__construct($logger, $watchdog, $pagerManager, $config);
69
70
    $this->dateFormatter = $dateFormatter;
71
    $this->rfcLogLevel = $rfcLogLevel;
72
73
    // Add terminal "/".
74
    $this->rootLength = mb_strlen(DRUPAL_ROOT) + 1;
0 ignored issues
show
Bug introduced by
The constant Drupal\mongodb_watchdog\Controller\DRUPAL_ROOT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
75
  }
76
77
  /**
78
   * Controller.
79
   *
80
   * @param \Symfony\Component\HttpFoundation\Request $request
81
   *   The current request.
82
   * @param string $uniqueId
83
   *   The unique request id from mod_unique_id. Unsafe.
84
   *
85
   * @return array<string,mixed>
86
   *   A render array.
87
   */
88
  public function build(Request $request, string $uniqueId): array {
89
    if (!preg_match('/^[-\w@]+$/', $uniqueId)) {
90
      throw new NotFoundHttpException('Request ID is not well-formed.');
91
    }
92
93
    $events = $this->getRowData($request, $uniqueId);
94
95
    if (empty($events)) {
96
      $top = [];
97
      $main = $this->buildEmpty($this->t('No events found for this request.'));
98
    }
99
    else {
100
      [, $first] = reset($events);
101
      $top = $this->getTop($uniqueId, $first);
102
      $main = $this->buildMainTable($events);
103
    }
104
105
    $ret = $this->buildDefaults($main, $top);
106
    return $ret;
107
  }
108
109
  /**
110
   * Build the main table.
111
   *
112
   * @param array<int,array{0:\Drupal\mongodb_watchdog\EventTemplate,1:\Drupal\mongodb_watchdog\Event}> $rows
113
   *   The event data, as row entries for a "table" element.
114
   *
115
   * @return array<string,mixed>
116
   *   A render array for the main table.
117
   */
118
  protected function buildMainTable(array $rows): array {
119
    $ret = [
120
      '#header' => $this->buildMainTableHeader(),
121
      '#rows' => $this->buildMainTableRows($rows),
122
      '#type' => 'table',
123
    ];
124
    return $ret;
125
  }
126
127
  /**
128
   * Build the main table header.
129
   *
130
   * @return \Drupal\Core\StringTranslation\TranslatableMarkup[]
131
   *   A "table" element header array.
132
   */
133
  protected function buildMainTableHeader(): array {
134
    $header = [
135
      $this->t('Sequence'),
136
      $this->t('Type'),
137
      $this->t('Severity'),
138
      $this->t('Event'),
139
      $this->t('File'),
140
      $this->t('Line'),
141
    ];
142
143
    return $header;
144
  }
145
146
  /**
147
   * Build the main table rows.
148
   *
149
   * @param array<int,array{0:\Drupal\mongodb_watchdog\EventTemplate, 1:\Drupal\mongodb_watchdog\Event}> $events
150
   *   A fully loaded array of events and their templates.
151
   *
152
   * @return array<int,mixed[]>
153
   *   A render array for a table.
154
   */
155
  protected function buildMainTableRows(array $events): array {
156
    $rows = [];
157
    $levels = $this->rfcLogLevel->getLevels();
158
    $event = NULL;
0 ignored issues
show
Unused Code introduced by
The assignment to $event is dead and can be removed.
Loading history...
159
    $template = NULL;
0 ignored issues
show
Unused Code introduced by
The assignment to $template is dead and can be removed.
Loading history...
160
161
    /** @var \Drupal\mongodb_watchdog\EventTemplate $template */
162
    /** @var \Drupal\mongodb_watchdog\Event $event */
163
    foreach ($events as [$template, $event]) {
164
      $row = [];
165
      $row[] = ['data' => $event->requestTracking_sequence];
166
      $row[] = $template->type;
167
      $row[] = [
168
        'data' => $levels[$template->severity],
169
        'class' => OverviewController::SEVERITY_CLASSES[$template->severity],
170
      ];
171
      $row[] = [
172
        'data' => Link::createFromRoute($template->asString($event->variables), 'mongodb_watchdog.reports.detail', [
0 ignored issues
show
Bug introduced by
It seems like $event->variables can also be of type null; however, parameter $variables of Drupal\mongodb_watchdog\EventTemplate::asString() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

172
        'data' => Link::createFromRoute($template->asString(/** @scrutinizer ignore-type */ $event->variables), 'mongodb_watchdog.reports.detail', [
Loading history...
173
          'eventTemplate' => $template->_id,
174
        ]),
175
      ];
176
      $row[] = $this->simplifyPath($event->variables['%file']);
177
      $row[] = $event->variables['%line'];
178
      $rows[] = $row;
179
    }
180
181
    return $rows;
182
  }
183
184
  /**
185
   * {@inheritdoc}
186
   */
187
  public static function create(ContainerInterface $container): self {
188
    /** @var \Psr\Log\LoggerInterface $logger */
189
    $logger = $container->get('logger.channel.mongodb_watchdog');
190
191
    /** @var \Drupal\mongodb_watchdog\Logger $watchdog */
192
    $watchdog = $container->get(Logger::SERVICE_LOGGER);
193
194
    /** @var \Drupal\Core\Config\ImmutableConfig $config */
195
    $config = $container->get('config.factory')->get('mongodb_watchdog.settings');
196
197
    /** @var \Drupal\Core\Datetime\DateFormatterInterface $dateFormatter */
198
    $dateFormatter = $container->get('date.formatter');
199
200
    /** @var \Drupal\Core\Pager\PagerManagerInterface $pagerManager */
201
    $pagerManager = $container->get('pager.manager');
202
203
    $rfcLogLevel = new RfcLogLevel();
204
205
    return new static($logger, $watchdog, $config, $dateFormatter, $pagerManager, $rfcLogLevel);
206
  }
207
208
  /**
209
   * Obtain the data from the logger.
210
   *
211
   * @param \Symfony\Component\HttpFoundation\Request $request
212
   *   The current request. Needed for paging.
213
   * @param string $uniqueId
214
   *   The request for which to build the detail page.
215
   *
216
   * @return array<int,array{0:\Drupal\mongodb_watchdog\EventTemplate,1:\Drupal\mongodb_watchdog\Event}>
217
   *   The data array.
218
   */
219
  protected function getRowData(Request $request, string $uniqueId): array {
220
    $count = $this->watchdog->requestEventsCount($uniqueId);
221
    $page = $this->setupPager($request, $count);
222
    $skip = $page * $this->itemsPerPage;
223
    $height = $this->itemsPerPage;
224
225
    $events = $this->watchdog->requestEvents($uniqueId, $skip, $height);
226
    return $events;
227
  }
228
229
  /**
230
   * Build the heading rows on the per-request event occurrences page.
231
   *
232
   * @param string $uniqueId
233
   *   The unique request id.
234
   * @param \Drupal\mongodb_watchdog\Event|null $first
235
   *   A fully loaded array of events and their templates.
236
   *
237
   * @return \Drupal\Core\StringTranslation\TranslatableMarkup[]
238
   *   A render array for a table.
239
   */
240
  protected function getTop(string $uniqueId = "", ?Event $first = NULL): array {
241
    $timestamp = isset($first->timestamp)
242
      ? $this->dateFormatter->format($first->timestamp, 'long')
243
      : $this->t('No information');
244
245
    $rows = [
246
      [$this->t('Request ID'), $uniqueId],
247
      [$this->t('Location'), $first->location()],
0 ignored issues
show
Bug introduced by
The method location() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

247
      [$this->t('Location'), $first->/** @scrutinizer ignore-call */ location()],

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
248
      [$this->t('Date/time'), $timestamp],
249
    ];
250
251
    foreach ($rows as &$row) {
252
      $row[0] = [
253
        'data' => $row[0],
254
        'header' => TRUE,
255
      ];
256
    }
257
258
    $ret = [
259
      '#caption' => $this->t('Request'),
260
      '#rows' => $rows,
261
      '#type' => 'table',
262
    ];
263
264
    return $ret;
265
  }
266
267
  /**
268
   * Convert an absolute path to a relative one if below the site root.
269
   *
270
   * @param string $path
271
   *   An absolute path on the filesystem.
272
   *
273
   * @return string
274
   *   A relative path if possible, otherwise the input path.
275
   */
276
  public function simplifyPath(string $path) {
277
    $ret = (mb_strpos($path, DRUPAL_ROOT) === 0)
0 ignored issues
show
Bug introduced by
The constant Drupal\mongodb_watchdog\Controller\DRUPAL_ROOT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
278
      ? mb_strpos($path, (string) $this->rootLength)
279
      : $path;
280
281
    return $ret;
282
  }
283
284
}
285