Completed
Pull Request — 8.x-2.x (#24)
by Frédéric G.
03:06
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
<?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\DependencyInjection\ContainerInjectionInterface;
9
use Drupal\Core\Link;
10
use Drupal\Core\Logger\RfcLogLevel;
11
use Drupal\mongodb_watchdog\Logger;
12
use Psr\Log\LoggerInterface;
13
use Symfony\Component\DependencyInjection\ContainerInterface;
14
use Symfony\Component\HttpFoundation\Request;
15
16
/**
17
 * Implements the controller for the request events page.
18
 */
19
class RequestController extends ControllerBase {
20
21
  /**
22
   * The core date.formatter service.
23
   *
24
   * @var \Drupal\Core\Datetime\DateFormatterInterface
25
   */
26
  protected $dateFormatter;
27
28
  /**
29
   * The length of the absolute path to the site root, in runes.
30
   *
31
   * @var int
32
   */
33
  protected $rootLength;
34
35
  /**
36
   * Controller constructor.
37
   *
38
   * @param \Psr\Log\LoggerInterface $logger
39
   *   The logger service, to log intervening events.
40
   * @param \Drupal\mongodb_watchdog\Logger $watchdog
41
   *   The MongoDB logger, to load stored events.
42
   * @param \Drupal\Core\Config\ImmutableConfig $config
43
   *   The module configuration.
44
   * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
45
   *   The core date.formatter service.
46
   */
47
  public function __construct(
48
    LoggerInterface $logger,
49
    Logger $watchdog,
50
    ImmutableConfig $config,
51
    DateFormatterInterface $date_formatter) {
52
    parent::__construct($logger, $watchdog, $config);
53
    $this->dateFormatter = $date_formatter;
54
55
    // Add terminal "/".
56
    $this->rootLength = Unicode::strlen(DRUPAL_ROOT) + 1;
57
  }
58
59
  /**
60
   * Controller.
61
   *
62
   * @param string $uniqueId
63
   *   The unique request id from mod_unique_id. Unsafe.
64
   *
65
   * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,string|array>.

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...
66
   *   A render array.
67
   */
68
  public function build(Request $request, $uniqueId) {
69
    if (!preg_match('/[\w-]+/', $uniqueId)) {
70
      return ['#markup' => ''];
71
    }
72
73
    $page = $this->setupPager($request, $uniqueId);
74
    $skip = $page * $this->itemsPerPage;
75
    $height = $this->itemsPerPage;
76
77
    $events = $this->watchdog->requestEvents($uniqueId, $skip, $height);
78
    $ret = [
79
      'request' => $this->buildRequest($uniqueId, $events),
80
      'events' => $this->buildRows($events),
81
      'pager' => [
82
        '#type' => 'pager',
83
      ],
84
      '#attached' => [
85
        'library' => ['mongodb_watchdog/styling'],
86
      ],
87
    ];
88
89
    return $ret;
90
  }
91
92
  /**
93
   * Build the top part of the page, about the request.
94
   *
95
   * @param string $unique_id
96
   *   The unique request id.
97
   * @param array<\Drupal\mongodb_watchdog\EventTemplate\Drupal\mongodb_watchdog\Event[]> $events
98
   *   A fully loaded array of events and their templates.
99
   *
100
   * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,string|array[]>.

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...
101
   *   A render array for a table.
102
   */
103
  public function buildRequest($unique_id, array $events) {
104
    if ($events) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $events of type Drupal\mongodb_watchdog\...godb_watchdog\Event[][] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
105
      $row = array_slice($events, 0, 1);
106
      /** @var \Drupal\mongodb_watchdog\Event $first */
107
      list($template, $first) = reset($row);
0 ignored issues
show
Unused Code introduced by
The assignment to $template is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
introduced by
Unused variable $template.
Loading history...
108
109
      $location = $first->location;
110
      $timestamp = isset($first->timestamp)
111
        ? $this->dateFormatter->format($first->timestamp, 'long')
112
        : t('No information');
113
    }
114
    else {
115
      $location = $timestamp = t('No information');
116
    }
117
118
    $rows = [
119
      [t('Request ID'), $unique_id],
120
      [t('Location'), $location],
121
      [t('Date/time'), $timestamp],
122
    ];
123
124
    foreach ($rows as &$row) {
125
      $row[0] = [
126
        'data' => $row[0],
127
        'header' => TRUE,
128
      ];
129
    }
130
131
    $ret = [
132
      '#type' => 'table',
133
      '#rows' => $rows,
134
    ];
135
    return $ret;
136
  }
137
138
  /**
139
   * Build the bottom part of the page, about the events during the request.
140
   *
141
   * @param array<\Drupal\mongodb_watchdog\EventTemplate\Drupal\mongodb_watchdog\Event[]> $events
142
   *   A fully loaded array of events and their templates.
143
   *
144
   * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,string|array>.

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...
145
   *   A render array for a table.
146
   */
147
  public function buildRows(array $events) {
148
    $header = [
149
      t('Sequence'),
150
      t('Type'),
151
      t('Severity'),
152
      t('Event'),
153
      t('File'),
154
      t('Line'),
155
    ];
156
    $rows = [];
157
    $levels = RfcLogLevel::getLevels();
158
159
    /** @var \Drupal\mongodb_watchdog\EventTemplate $template */
160
    /** @var \Drupal\mongodb_watchdog\Event $event */
161
    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...
162
      $row = [
163
        ['data' => $event->requestTracking_sequence],
0 ignored issues
show
introduced by
Variable $event is undefined.
Loading history...
164
        $template->type,
0 ignored issues
show
introduced by
Variable $template is undefined.
Loading history...
165
        [
166
          'data' => $levels[$template->severity],
0 ignored issues
show
introduced by
Variable $template is undefined.
Loading history...
167
          'class' => OverviewController::SEVERITY_CLASSES[$template->severity],
0 ignored issues
show
introduced by
Variable $template is undefined.
Loading history...
168
        ],
169
        [
170
          '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...
171
            'event_template' => $template->_id,
0 ignored issues
show
introduced by
Variable $template is undefined.
Loading history...
172
          ]),
173
        ],
174
        $this->simplifyPath($event->variables['%file']),
0 ignored issues
show
introduced by
Variable $event is undefined.
Loading history...
175
        $event->variables['%line'],
0 ignored issues
show
introduced by
Variable $event is undefined.
Loading history...
176
      ];
177
      $rows[] = $row;
178
    }
179
180
    $ret = [
181
      '#type' => 'table',
182
      '#header' => $header,
183
      '#rows' => $rows,
184
    ];
185
186
    return $ret;
187
  }
188
189
  /**
190
   * {@inheritdoc}
191
   */
192 View Code Duplication
  public static function create(ContainerInterface $container) {
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...
193
    /** @var \Psr\Log\LoggerInterface $logger */
194
    $logger = $container->get('logger.channel.mongodb_watchdog');
195
196
    /** @var \Drupal\mongodb_watchdog\Logger $watchdog */
197
    $watchdog = $container->get('mongodb.logger');
198
199
    /** @var \Drupal\Core\Config\ImmutableConfig $config */
200
    $config = $container->get('config.factory')->get('mongodb_watchdog.settings');
201
202
    /** @var \Drupal\Core\Datetime\DateFormatterInterface $date_formatter */
203
    $date_formatter = $container->get('date.formatter');
204
205
    return new static($logger, $watchdog, $config, $date_formatter);
206
  }
207
208
  /**
209
   * Set up the pager.
210
   *
211
   * @param \Symfony\Component\HttpFoundation\Request $request
212
   *   The current request.
213
   * @param int $uniqueId
214
   *   The uniqueId of the current request.
215
   *
216
   * @return int
217
   *   The number of the page to display, starting at 0.
218
   */
219 View Code Duplication
  public function setupPager(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...
220
    $count = $this->watchdog->requestEventsCount($uniqueId);
221
    $height = $this->itemsPerPage;
222
    pager_default_initialize($count, $height);
223
224
    $page = intval($request->query->get('page'));
225
    if ($page < 0) {
226
      $page = 0;
227
    }
228
    else {
229
      $page_max = intval(min(ceil($count / $height), PHP_INT_MAX) - 1);
230
      if ($page > $page_max) {
231
        $page = $page_max;
232
      }
233
    }
234
235
    return $page;
236
  }
237
238
  /**
239
   * Convert an absolute path to a relative one if below the site root.
240
   *
241
   * @param string $path
242
   *   An absolute path on the filesystem.
243
   *
244
   * @return string
245
   *   A relative path if possible, otherwise the input path.
246
   */
247
  public function simplifyPath($path) {
248
    $ret = (Unicode::strpos($path, DRUPAL_ROOT) === 0)
249
      ? Unicode::substr($path, $this->rootLength)
250
      : $path;
251
    return $ret;
252
  }
253
254
}
0 ignored issues
show
Coding Style introduced by
As per coding style, files should not end with a newline character.

This check marks files that end in a newline character, i.e. an empy line.

Loading history...
255