Completed
Pull Request — 8.x-2.x (#24)
by Frédéric G.
02:40
created

RequestController::buildTrackRequest()   B

Complexity

Conditions 4
Paths 6

Size

Total Lines 34
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 22
c 1
b 0
f 0
nc 6
nop 2
dl 0
loc 34
rs 8.5806

1 Method

Rating   Name   Duplication   Size   Complexity  
A RequestController::build() 0 20 3
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
   * The length of the absolute path to the site root, in runes.
31
   *
32
   * @var int
33
   */
34
  protected $rootLength;
35
36
  /**
37
   * A Unicode instance, to avoid static access.
38
   *
39
   * @var \Drupal\Component\Utility\Unicode
40
   */
41
  protected $unicode;
42
43
  /**
44
   * Controller constructor.
45
   *
46
   * @param \Psr\Log\LoggerInterface $logger
47
   *   The logger service, to log intervening events.
48
   * @param \Drupal\mongodb_watchdog\Logger $watchdog
49
   *   The MongoDB logger, to load stored events.
50
   * @param \Drupal\Core\Config\ImmutableConfig $config
51
   *   The module configuration.
52
   * @param \Drupal\Core\Datetime\DateFormatterInterface $dateFormatter
53
   *   The core date.formatter service.
54
   * @param \Drupal\Component\Utility\Unicode $unicode
55
   *   A Unicode instance, to avoid static access.
56
   */
57
  public function __construct(
58
    LoggerInterface $logger,
59
    Logger $watchdog,
60
    ImmutableConfig $config,
61
    DateFormatterInterface $dateFormatter,
62
    Unicode $unicode,
63
    RfcLogLevel $rfcLogLevel,
64
    Link $link) {
65
    parent::__construct($logger, $watchdog, $config);
66
67
    $this->dateFormatter = $dateFormatter;
68
    $this->link = $link;
69
    $this->rfcLogLevel = $rfcLogLevel;
70
    $this->unicode = $unicode;
71
72
    // Add terminal "/".
73
    $this->rootLength = $this->unicode->strlen(DRUPAL_ROOT) + 1;
74
  }
75
76
  /**
77
   * Controller.
78
   *
79
   * @param \Symfony\Component\HttpFoundation\Request $request
80
   *   The current request.
81
   * @param string $uniqueId
82
   *   The unique request id from mod_unique_id. Unsafe.
83
   *
84
   * @return array<string,string|array>
85
   *   A render array.
86
   */
87
  public function build(Request $request, $uniqueId) {
88
    if (!preg_match('/^[\w-]+$/', $uniqueId)) {
89
      throw new NotFoundHttpException(t('Request ID is not well-formed.'));
90
    }
91
92
    $events = $this->getRowData($request, $uniqueId);
93
94
    if (empty($events)) {
95
      $top = NULL;
96
      $main = $this->buildEmpty(t('No events found for this request.'));
97
    }
98
    else {
99
      list(, $first) = reset($events);
100
      $top = $this->getTop($uniqueId, $first);
101
      $main = $this->buildMainTable($events);
102
    }
103
104
    $ret = $this->buildDefaults($main, $top);
105
    return $ret;
106
  }
107
108
  /**
109
   * Build the main table.
110
   *
111
   * @param array $rows
112
   *   The event data.
113
   *
114
   * @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...
115
   *   A render array for the main table.
116
   */
117 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...
118
    $ret = [
119
      '#header' => $this->buildMainTableHeader(),
120
      '#rows' => $this->buildMainTableRows($rows),
121
      '#type' => 'table',
122
    ];
123
    return $ret;
124
  }
125
126
  /**
127
   * Build the main table header.
128
   *
129
   * @return \Drupal\Core\StringTranslation\TranslatableMarkup[]
130
   *   A table header array.
131
   */
132
  protected function buildMainTableHeader() {
133
    $header = [
134
      t('Sequence'),
135
      t('Type'),
136
      t('Severity'),
137
      t('Event'),
138
      t('File'),
139
      t('Line'),
140
    ];
141
142
    return $header;
143
  }
144
145
  /**
146
   * Build the main table rows.
147
   *
148
   * @param array<\Drupal\mongodb_watchdog\EventTemplate\Drupal\mongodb_watchdog\Event[]> $events
149
   *   A fully loaded array of events and their templates.
150
   *
151
   * @return array<string,array|string>
152
   *   A render array for a table.
153
   */
154
  protected function buildMainTableRows(array $events) {
155
    $rows = [];
156
    $levels = $this->rfcLogLevel->getLevels();
157
158
    /** @var \Drupal\mongodb_watchdog\EventTemplate $template */
159
    /** @var \Drupal\mongodb_watchdog\Event $event */
160
    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...
161
      $row = [];
162
      $row[] = ['data' => $event->requestTracking_sequence];
0 ignored issues
show
introduced by
Variable $event is undefined.
Loading history...
163
      $row[] = $template->type;
0 ignored issues
show
introduced by
Variable $template is undefined.
Loading history...
164
      $row[] = [
165
        'data' => $levels[$template->severity],
0 ignored issues
show
introduced by
Variable $template is undefined.
Loading history...
166
        'class' => OverviewController::SEVERITY_CLASSES[$template->severity],
0 ignored issues
show
introduced by
Variable $template is undefined.
Loading history...
167
      ];
168
      $row[] = [
169
        'data' => $this->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...
170
          'eventTemplate' => $template->_id,
0 ignored issues
show
introduced by
Variable $template is undefined.
Loading history...
171
        ]),
172
      ];
173
      $row[] = $this->simplifyPath($event->variables['%file']);
0 ignored issues
show
introduced by
Variable $event is undefined.
Loading history...
174
      $row[] = $event->variables['%line'];
0 ignored issues
show
introduced by
Variable $event is undefined.
Loading history...
175
      $rows[] = $row;
176
    }
177
178
    return $rows;
179
  }
180
181
  /**
182
   * {@inheritdoc}
183
   */
184
  public static function create(ContainerInterface $container) {
185
    /** @var \Psr\Log\LoggerInterface $logger */
186
    $logger = $container->get('logger.channel.mongodb_watchdog');
187
188
    /** @var \Drupal\mongodb_watchdog\Logger $watchdog */
189
    $watchdog = $container->get('mongodb.logger');
190
191
    /** @var \Drupal\Core\Config\ImmutableConfig $config */
192
    $config = $container->get('config.factory')->get('mongodb_watchdog.settings');
193
194
    /** @var \Drupal\Core\Datetime\DateFormatterInterface $dateFormatter */
195
    $dateFormatter = $container->get('date.formatter');
196
197
    $link = new Link();
198
    $rfcLogLevel = new RfcLogLevel();
199
    $unicode = new Unicode();
200
201
    return new static($logger, $watchdog, $config, $dateFormatter, $unicode, $rfcLogLevel, $link);
202
  }
203
204
  /**
205
   * Obtain the data from the logger.
206
   *
207
   * @param \Symfony\Component\HttpFoundation\Request $request
208
   *   The current request. Needed for paging.
209
   * @param string $uniqueId
210
   *   The request for which to build the detail page.
211
   *
212
   * @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...
213
   *   The data array.
214
   */
215 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...
216
    $count = $this->watchdog->requestEventsCount($uniqueId);
217
    $page = $this->setupPager($request, $count);
218
    $skip = $page * $this->itemsPerPage;
219
    $height = $this->itemsPerPage;
220
221
    $events = $this->watchdog->requestEvents($uniqueId, $skip, $height);
222
    return $events;
223
  }
224
225
  /**
226
   * Build the heading rows on the per-request event occurrences page.
227
   *
228
   * @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...
229
   *   The unique request id.
230
   * @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...
231
   *   A fully loaded array of events and their templates.
232
   *
233
   * @return \Drupal\Core\StringTranslation\TranslatableMarkup[]
234
   *   A render array for a table.
235
   */
236
  protected function getTop($uniqueId = NULL, Event $first = NULL) {
237
    $location = $first->location;
238
    $timestamp = isset($first->timestamp)
239
      ? $this->dateFormatter->format($first->timestamp, 'long')
240
      : t('No information');
241
242
    $rows = [
243
      [t('Request ID'), $uniqueId],
244
      [t('Location'), $location],
245
      [t('Date/time'), $timestamp],
246
    ];
247
248
    foreach ($rows as &$row) {
249
      $row[0] = [
250
        'data' => $row[0],
251
        'header' => TRUE,
252
      ];
253
    }
254
255
    $ret = [
256
      '#caption' => t('Request'),
257
      '#rows' => $rows,
258
      '#type' => 'table',
259
    ];
260
261
    return $ret;
262
  }
263
264
  /**
265
   * Convert an absolute path to a relative one if below the site root.
266
   *
267
   * @param string $path
268
   *   An absolute path on the filesystem.
269
   *
270
   * @return string
271
   *   A relative path if possible, otherwise the input path.
272
   */
273
  public function simplifyPath($path) {
274
    $ret = ($this->unicode->strpos($path, DRUPAL_ROOT) === 0)
275
      ? $this->unicode->substr($path, $this->rootLength)
276
      : $path;
277
278
    return $ret;
279
  }
280
281
}
282