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

src/Controller/RequestController.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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
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
103
   *   A render array for a table.
104
   */
105
  public function buildRequest($unique_id, array $events) {
106
    if ($events) {
107
      $row = array_slice($events, 0, 1);
108
      /** @var \Drupal\mongodb_watchdog\Event $first */
109
      list($template, $first) = reset($row);
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)) {
164
      $row = [
165
        ['data' => $event->requestTracking_sequence],
166
        $template->type,
167
        [
168
          'data' => $levels[$template->severity],
169
          'class' => OverviewController::SEVERITY_CLASSES[$template->severity],
170
        ],
171
        [
172
          'data' => Link::createFromRoute($template->asString($event->variables), 'mongodb_watchdog.reports.detail', [
173
            'event_template' => $template->_id,
174
          ]),
175
        ],
176
        $this->simplifyPath($event->variables['%file']),
177
        $event->variables['%line'],
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) {
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