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

RequestController::track()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 22
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 15
c 1
b 0
f 0
nc 2
nop 2
dl 0
loc 22
rs 9.2
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\Logger;
11
use Psr\Log\LoggerInterface;
12
use Symfony\Component\DependencyInjection\ContainerInterface;
13
use Symfony\Component\HttpFoundation\Request;
14
15
/**
16
 * Implements the controller for the request events page.
17
 */
18
class RequestController extends ControllerBase {
19
20
  /**
21
   * The core date.formatter service.
22
   *
23
   * @var \Drupal\Core\Datetime\DateFormatterInterface
24
   */
25
  protected $dateFormatter;
26
27
  /**
28
   * The length of the absolute path to the site root, in runes.
29
   *
30
   * @var int
31
   */
32
  protected $rootLength;
33
34
  /**
35
   * Controller constructor.
36
   *
37
   * @param \Psr\Log\LoggerInterface $logger
38
   *   The logger service, to log intervening events.
39
   * @param \Drupal\mongodb_watchdog\Logger $watchdog
40
   *   The MongoDB logger, to load stored events.
41
   * @param \Drupal\Core\Config\ImmutableConfig $config
42
   *   The module configuration.
43
   * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
44
   *   The core date.formatter service.
45
   */
46
  public function __construct(
47
    LoggerInterface $logger,
48
    Logger $watchdog,
49
    ImmutableConfig $config,
50
    DateFormatterInterface $date_formatter) {
51
    parent::__construct($logger, $watchdog, $config);
52
    $this->dateFormatter = $date_formatter;
53
54
    // Add terminal "/".
55
    $this->rootLength = Unicode::strlen(DRUPAL_ROOT) + 1;
56
  }
57
58
  /**
59
   * Controller.
60
   *
61
   * @param \Symfony\Component\HttpFoundation\Request $request
62
   *   The current request.
63
   * @param string $uniqueId
64
   *   The unique request id from mod_unique_id. Unsafe.
65
   *
66
   * @return array <string,array|string>
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...
67
   *   A render array.
68
   */
69
  public function build(Request $request, $uniqueId) {
70
    if (!preg_match('/[\w-]+/', $uniqueId)) {
71
      return ['#markup' => ''];
72
    }
73
74
    $count = $this->watchdog->requestEventsCount($uniqueId);
75
    $page = $this->setupPager($request, $count);
76
    $skip = $page * $this->itemsPerPage;
77
    $height = $this->itemsPerPage;
78
79
    $events = $this->watchdog->requestEvents($uniqueId, $skip, $height);
80
    $ret = [
81
      'request' => $this->buildRequest($uniqueId, $events),
82
      'events' => $this->buildRows($events),
83
      'pager' => [
84
        '#type' => 'pager',
85
      ],
86
      '#attached' => [
87
        'library' => ['mongodb_watchdog/styling'],
88
      ],
89
    ];
90
91
    return $ret;
92
  }
93
94
  /**
95
   * Build the top part of the page, about the request.
96
   *
97
   * @param string $unique_id
98
   *   The unique request id.
99
   * @param array<\Drupal\mongodb_watchdog\EventTemplate\Drupal\mongodb_watchdog\Event[]> $events
100
   *   A fully loaded array of events and their templates.
101
   *
102
   * @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...
103
   *   A render array for a table.
104
   */
105
  public function buildRequest($unique_id, array $events) {
106
    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...
107
      $row = array_slice($events, 0, 1);
108
      /** @var \Drupal\mongodb_watchdog\Event $first */
109
      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...
110
111
      $location = $first->location;
112
      $timestamp = isset($first->timestamp)
113
        ? $this->dateFormatter->format($first->timestamp, 'long')
114
        : t('No information');
115
    }
116
    else {
117
      $location = $timestamp = t('No information');
118
    }
119
120
    $rows = [
121
      [t('Request ID'), $unique_id],
122
      [t('Location'), $location],
123
      [t('Date/time'), $timestamp],
124
    ];
125
126
    foreach ($rows as &$row) {
127
      $row[0] = [
128
        'data' => $row[0],
129
        'header' => TRUE,
130
      ];
131
    }
132
133
    $ret = [
134
      '#type' => 'table',
135
      '#rows' => $rows,
136
    ];
137
    return $ret;
138
  }
139
140
  /**
141
   * Build the bottom part of the page, about the events during the request.
142
   *
143
   * @param array<\Drupal\mongodb_watchdog\EventTemplate\Drupal\mongodb_watchdog\Event[]> $events
144
   *   A fully loaded array of events and their templates.
145
   *
146
   * @return array<string,array|string> 
147
   *   A render array for a table.
148
   */
149
  public function buildRows(array $events) {
150
    $header = [
151
      t('Sequence'),
152
      t('Type'),
153
      t('Severity'),
154
      t('Event'),
155
      t('File'),
156
      t('Line'),
157
    ];
158
    $rows = [];
159
    $levels = RfcLogLevel::getLevels();
160
161
    /** @var \Drupal\mongodb_watchdog\EventTemplate $template */
162
    /** @var \Drupal\mongodb_watchdog\Event $event */
163
    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...
164
      $row = [
165
        ['data' => $event->requestTracking_sequence],
0 ignored issues
show
introduced by
Variable $event is undefined.
Loading history...
166
        $template->type,
0 ignored issues
show
introduced by
Variable $template is undefined.
Loading history...
167
        [
168
          'data' => $levels[$template->severity],
0 ignored issues
show
introduced by
Variable $template is undefined.
Loading history...
169
          'class' => OverviewController::SEVERITY_CLASSES[$template->severity],
0 ignored issues
show
introduced by
Variable $template is undefined.
Loading history...
170
        ],
171
        [
172
          '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...
173
            'event_template' => $template->_id,
0 ignored issues
show
introduced by
Variable $template is undefined.
Loading history...
174
          ]),
175
        ],
176
        $this->simplifyPath($event->variables['%file']),
0 ignored issues
show
introduced by
Variable $event is undefined.
Loading history...
177
        $event->variables['%line'],
0 ignored issues
show
introduced by
Variable $event is undefined.
Loading history...
178
      ];
179
      $rows[] = $row;
180
    }
181
182
    $ret = [
183
      '#type' => 'table',
184
      '#header' => $header,
185
      '#rows' => $rows,
186
    ];
187
188
    return $ret;
189
  }
190
191
  /**
192
   * {@inheritdoc}
193
   */
194 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...
195
    /** @var \Psr\Log\LoggerInterface $logger */
196
    $logger = $container->get('logger.channel.mongodb_watchdog');
197
198
    /** @var \Drupal\mongodb_watchdog\Logger $watchdog */
199
    $watchdog = $container->get('mongodb.logger');
200
201
    /** @var \Drupal\Core\Config\ImmutableConfig $config */
202
    $config = $container->get('config.factory')->get('mongodb_watchdog.settings');
203
204
    /** @var \Drupal\Core\Datetime\DateFormatterInterface $date_formatter */
205
    $date_formatter = $container->get('date.formatter');
206
207
    return new static($logger, $watchdog, $config, $date_formatter);
208
  }
209
210
  /**
211
   * Convert an absolute path to a relative one if below the site root.
212
   *
213
   * @param string $path
214
   *   An absolute path on the filesystem.
215
   *
216
   * @return string
217
   *   A relative path if possible, otherwise the input path.
218
   */
219
  public function simplifyPath($path) {
220
    $ret = (Unicode::strpos($path, DRUPAL_ROOT) === 0)
221
      ? Unicode::substr($path, $this->rootLength)
222
      : $path;
223
    return $ret;
224
  }
225
226
}
227