Completed
Push — 8.x-2.x ( 74e505...ec080d )
by Frédéric G.
03:07
created

RequestController::buildMainTableHeader()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 9
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 12
rs 9.4285
1
<?php
2
3
namespace Drupal\mongodb_watchdog\Controller;
4
5
use Drupal\Component\Utility\Unicode;
6
use Drupal\Core\Config\ImmutableConfig;
7
use Drupal\Core\Datetime\DateFormatterInterface;
8
use Drupal\Core\Link;
9
use Drupal\Core\Logger\RfcLogLevel;
10
use Drupal\mongodb_watchdog\Event;
11
use Drupal\mongodb_watchdog\Logger;
12
use Psr\Log\LoggerInterface;
13
use Symfony\Component\DependencyInjection\ContainerInterface;
14
use Symfony\Component\HttpFoundation\Request;
15
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
16
17
/**
18
 * The controller for the request events page.
19
 */
20
class RequestController extends ControllerBase {
21
22
  /**
23
   * The core date.formatter service.
24
   *
25
   * @var \Drupal\Core\Datetime\DateFormatterInterface
26
   */
27
  protected $dateFormatter;
28
29
  /**
30
   * A RfcLogLevel instance, to avoid static access.
31
   *
32
   * @var \Drupal\Core\Logger\RfcLogLevel
33
   */
34
  protected $rfcLogLevel;
35
36
  /**
37
   * The length of the absolute path to the site root, in runes.
38
   *
39
   * @var int
40
   */
41
  protected $rootLength;
42
43
  /**
44
   * A Unicode instance, to avoid static access.
45
   *
46
   * @var \Drupal\Component\Utility\Unicode
47
   */
48
  protected $unicode;
49
50
  /**
51
   * Controller constructor.
52
   *
53
   * @param \Psr\Log\LoggerInterface $logger
54
   *   The logger service, to log intervening events.
55
   * @param \Drupal\mongodb_watchdog\Logger $watchdog
56
   *   The MongoDB logger, to load stored events.
57
   * @param \Drupal\Core\Config\ImmutableConfig $config
58
   *   The module configuration.
59
   * @param \Drupal\Core\Datetime\DateFormatterInterface $dateFormatter
60
   *   The core date.formatter service.
61
   * @param \Drupal\Component\Utility\Unicode $unicode
62
   *   A Unicode instance, to avoid static access.
63
   * @param \Drupal\Core\Logger\RfcLogLevel $rfcLogLevel
64
   *   A RfcLogLevel instance, to avoid static access.
65
   */
66 View Code Duplication
  public function __construct(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
67
    LoggerInterface $logger,
68
    Logger $watchdog,
69
    ImmutableConfig $config,
70
    DateFormatterInterface $dateFormatter,
71
    Unicode $unicode,
72
    RfcLogLevel $rfcLogLevel) {
73
    parent::__construct($logger, $watchdog, $config);
74
75
    $this->dateFormatter = $dateFormatter;
76
    $this->rfcLogLevel = $rfcLogLevel;
77
    $this->unicode = $unicode;
78
79
    // Add terminal "/".
80
    $this->rootLength = $this->unicode->strlen(DRUPAL_ROOT) + 1;
81
  }
82
83
  /**
84
   * Controller.
85
   *
86
   * @param \Symfony\Component\HttpFoundation\Request $request
87
   *   The current request.
88
   * @param string $uniqueId
89
   *   The unique request id from mod_unique_id. Unsafe.
90
   *
91
   * @return array<string,string|array>
92
   *   A render array.
93
   */
94
  public function build(Request $request, $uniqueId) {
95
    if (!preg_match('/^[\w-@]+$/', $uniqueId)) {
96
      throw new NotFoundHttpException(t('Request ID is not well-formed.'));
97
    }
98
99
    $events = $this->getRowData($request, $uniqueId);
100
101
    if (empty($events)) {
102
      $top = NULL;
103
      $main = $this->buildEmpty(t('No events found for this request.'));
104
    }
105
    else {
106
      list(, $first) = reset($events);
107
      $top = $this->getTop($uniqueId, $first);
108
      $main = $this->buildMainTable($events);
109
    }
110
111
    $ret = $this->buildDefaults($main, $top);
112
    return $ret;
113
  }
114
115
  /**
116
   * Build the main table.
117
   *
118
   * @param array $rows
119
   *   The event data.
120
   *
121
   * @return array<string,string|array>
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,\Drupal\Cor...g,array|string>|string>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
122
   *   A render array for the main table.
123
   */
124 View Code Duplication
  protected function buildMainTable(array $rows) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
125
    $ret = [
126
      '#header' => $this->buildMainTableHeader(),
127
      '#rows' => $this->buildMainTableRows($rows),
128
      '#type' => 'table',
129
    ];
130
    return $ret;
131
  }
132
133
  /**
134
   * Build the main table header.
135
   *
136
   * @return \Drupal\Core\StringTranslation\TranslatableMarkup[]
137
   *   A table header array.
138
   */
139
  protected function buildMainTableHeader() {
140
    $header = [
141
      t('Sequence'),
142
      t('Type'),
143
      t('Severity'),
144
      t('Event'),
145
      t('File'),
146
      t('Line'),
147
    ];
148
149
    return $header;
150
  }
151
152
  /**
153
   * Build the main table rows.
154
   *
155
   * @param array<\Drupal\mongodb_watchdog\EventTemplate\Drupal\mongodb_watchdog\Event[]> $events
156
   *   A fully loaded array of events and their templates.
157
   *
158
   * @return array<string,array|string>
159
   *   A render array for a table.
160
   */
161
  protected function buildMainTableRows(array $events) {
162
    $rows = [];
163
    $levels = $this->rfcLogLevel->getLevels();
164
165
    /** @var \Drupal\mongodb_watchdog\EventTemplate $template */
166
    /** @var \Drupal\mongodb_watchdog\Event $event */
167
    foreach ($events as list($template, $event)) {
0 ignored issues
show
introduced by
Variable $template is undefined.
Loading history...
introduced by
Variable $event is undefined.
Loading history...
168
      $row = [];
169
      $row[] = ['data' => $event->requestTracking_sequence];
0 ignored issues
show
introduced by
Variable $event is undefined.
Loading history...
170
      $row[] = $template->type;
0 ignored issues
show
introduced by
Variable $template is undefined.
Loading history...
171
      $row[] = [
172
        'data' => $levels[$template->severity],
0 ignored issues
show
introduced by
Variable $template is undefined.
Loading history...
173
        'class' => OverviewController::SEVERITY_CLASSES[$template->severity],
0 ignored issues
show
introduced by
Variable $template is undefined.
Loading history...
174
      ];
175
      $row[] = [
176
        'data' => Link::createFromRoute($template->asString($event->variables), 'mongodb_watchdog.reports.detail', [
0 ignored issues
show
introduced by
Variable $template is undefined.
Loading history...
introduced by
Variable $event is undefined.
Loading history...
177
          'eventTemplate' => $template->_id,
0 ignored issues
show
introduced by
Variable $template is undefined.
Loading history...
178
        ]),
179
      ];
180
      $row[] = $this->simplifyPath($event->variables['%file']);
0 ignored issues
show
introduced by
Variable $event is undefined.
Loading history...
181
      $row[] = $event->variables['%line'];
0 ignored issues
show
introduced by
Variable $event is undefined.
Loading history...
182
      $rows[] = $row;
183
    }
184
185
    return $rows;
186
  }
187
188
  /**
189
   * {@inheritdoc}
190
   */
191
  public static function create(ContainerInterface $container) {
192
    /** @var \Psr\Log\LoggerInterface $logger */
193
    $logger = $container->get('logger.channel.mongodb_watchdog');
194
195
    /** @var \Drupal\mongodb_watchdog\Logger $watchdog */
196
    $watchdog = $container->get('mongodb.logger');
197
198
    /** @var \Drupal\Core\Config\ImmutableConfig $config */
199
    $config = $container->get('config.factory')->get('mongodb_watchdog.settings');
200
201
    /** @var \Drupal\Core\Datetime\DateFormatterInterface $dateFormatter */
202
    $dateFormatter = $container->get('date.formatter');
203
204
    $rfcLogLevel = new RfcLogLevel();
205
    $unicode = new Unicode();
206
207
    return new static($logger, $watchdog, $config, $dateFormatter, $unicode, $rfcLogLevel);
208
  }
209
210
  /**
211
   * Obtain the data from the logger.
212
   *
213
   * @param \Symfony\Component\HttpFoundation\Request $request
214
   *   The current request. Needed for paging.
215
   * @param string $uniqueId
216
   *   The request for which to build the detail page.
217
   *
218
   * @return \Drupal\mongodb_watchdog\Event[]
0 ignored issues
show
Documentation introduced by
Should the return type not be \Drupal\mongodb_watchdog...godb_watchdog\Event[][]?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
219
   *   The data array.
220
   */
221 View Code Duplication
  protected function getRowData(Request $request, $uniqueId) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
222
    $count = $this->watchdog->requestEventsCount($uniqueId);
223
    $page = $this->setupPager($request, $count);
224
    $skip = $page * $this->itemsPerPage;
225
    $height = $this->itemsPerPage;
226
227
    $events = $this->watchdog->requestEvents($uniqueId, $skip, $height);
228
    return $events;
229
  }
230
231
  /**
232
   * Build the heading rows on the per-request event occurrences page.
233
   *
234
   * @param string $uniqueId
0 ignored issues
show
Documentation introduced by
Should the type for parameter $uniqueId not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
235
   *   The unique request id.
236
   * @param \Drupal\mongodb_watchdog\Event $first
0 ignored issues
show
Documentation introduced by
Should the type for parameter $first not be null|Event?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
237
   *   A fully loaded array of events and their templates.
238
   *
239
   * @return \Drupal\Core\StringTranslation\TranslatableMarkup[]
240
   *   A render array for a table.
241
   */
242
  protected function getTop($uniqueId = NULL, Event $first = NULL) {
243
    $location = $first->location;
244
    $timestamp = isset($first->timestamp)
245
      ? $this->dateFormatter->format($first->timestamp, 'long')
246
      : t('No information');
247
248
    $rows = [
249
      [t('Request ID'), $uniqueId],
250
      [t('Location'), $location],
251
      [t('Date/time'), $timestamp],
252
    ];
253
254
    foreach ($rows as &$row) {
255
      $row[0] = [
256
        'data' => $row[0],
257
        'header' => TRUE,
258
      ];
259
    }
260
261
    $ret = [
262
      '#caption' => t('Request'),
263
      '#rows' => $rows,
264
      '#type' => 'table',
265
    ];
266
267
    return $ret;
268
  }
269
270
  /**
271
   * Convert an absolute path to a relative one if below the site root.
272
   *
273
   * @param string $path
274
   *   An absolute path on the filesystem.
275
   *
276
   * @return string
277
   *   A relative path if possible, otherwise the input path.
278
   */
279
  public function simplifyPath($path) {
280
    $ret = ($this->unicode->strpos($path, DRUPAL_ROOT) === 0)
281
      ? $this->unicode->substr($path, $this->rootLength)
282
      : $path;
283
284
    return $ret;
285
  }
286
287
}
288