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

OverviewController::getEventLink()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 21
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 14
c 0
b 0
f 0
nc 3
nop 1
dl 0
loc 21
rs 9.3142
1
<?php
2
3
namespace Drupal\mongodb_watchdog\Controller;
4
5
use Drupal\Component\Utility\SafeMarkup;
6
use Drupal\Component\Utility\Unicode;
7
use Drupal\Core\Config\ImmutableConfig;
8
use Drupal\Core\Datetime\DateFormatterInterface;
9
use Drupal\Core\Extension\ModuleHandlerInterface;
10
use Drupal\Core\Form\FormBuilderInterface;
11
use Drupal\Core\Link;
12
use Drupal\Core\Logger\RfcLogLevel;
13
use Drupal\mongodb_watchdog\Event;
14
use Drupal\mongodb_watchdog\EventTemplate;
15
use Drupal\mongodb_watchdog\Form\OverviewFilterForm;
16
use Drupal\mongodb_watchdog\Logger;
17
use Psr\Log\LogLevel;
18
use Psr\Log\LoggerInterface;
19
use Symfony\Component\DependencyInjection\ContainerInterface;
20
use Symfony\Component\HttpFoundation\Request;
21
22
/**
23
 * Class OverviewController provides the main MongoDB Watchdog report page.
24
 */
25
class OverviewController extends ControllerBase {
26
  const EVENT_TYPE_MAP = [
27
    'typeMap' => [
28
      'array' => 'array',
29
      'document' => 'array',
30
      'root' => 'Drupal\mongodb_watchdog\Event',
31
    ],
32
  ];
33
  const SEVERITY_PREFIX = 'mongodb_watchdog__severity_';
34
  const SEVERITY_CLASSES = [
35
    RfcLogLevel::DEBUG => self::SEVERITY_PREFIX . LogLevel::DEBUG,
36
    RfcLogLevel::INFO => self::SEVERITY_PREFIX . LogLevel::INFO,
37
    RfcLogLevel::NOTICE => self::SEVERITY_PREFIX . LogLevel::NOTICE,
38
    RfcLogLevel::WARNING => self::SEVERITY_PREFIX . LogLevel::WARNING,
39
    RfcLogLevel::ERROR => self::SEVERITY_PREFIX . LogLevel::ERROR,
40
    RfcLogLevel::CRITICAL => self::SEVERITY_PREFIX . LogLevel::CRITICAL,
41
    RfcLogLevel::ALERT => self::SEVERITY_PREFIX . LogLevel::ALERT,
42
    RfcLogLevel::EMERGENCY => self::SEVERITY_PREFIX . LogLevel::EMERGENCY,
43
  ];
44
45
  /**
46
   * The core date.formatter service.
47
   *
48
   * @var \Drupal\Core\Datetime\DateFormatterInterface
49
   */
50
  protected $dateFormatter;
51
52
  /**
53
   * The form builder service.
54
   *
55
   * @var \Drupal\Core\Form\FormBuilderInterface
56
   */
57
  protected $formBuilder;
58
59
  /**
60
   * The module handler service.
61
   *
62
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
63
   */
64
  protected $moduleHandler;
65
66
  /**
67
   * The length of the disk path to DRUPAL_ROOT.
68
   *
69
   * @var int
70
   *
71
   * @see \Drupal\mongodb_watchdog\Controller\OverviewController::getEventSource()
72
   */
73
  protected $rootLength;
74
75
  /**
76
   * Controller constructor.
77
   *
78
   * @param \Psr\Log\LoggerInterface $logger
79
   *   The logger service, to log intervening events.
80
   * @param \Drupal\mongodb_watchdog\Logger $watchdog
81
   *   The MongoDB logger, to load stored events.
82
   * @param \Drupal\Core\Config\ImmutableConfig $config
83
   *   The module configuration.
84
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
85
   *   A module handler.
86
   * @param \Drupal\Core\Form\FormBuilderInterface $form_builder
87
   *   The form builder service.
88
   * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
89
   *   The core date_formatter service.
90
   */
91
  public function __construct(
92
    LoggerInterface $logger,
93
    Logger $watchdog,
94
    ImmutableConfig $config,
95
    ModuleHandlerInterface $module_handler,
96
    FormBuilderInterface $form_builder,
97
    DateFormatterInterface $date_formatter) {
98
    parent::__construct($logger, $watchdog, $config);
99
100
    $this->dateFormatter = $date_formatter;
101
    $this->formBuilder = $form_builder;
102
    $this->moduleHandler = $module_handler;
103
104
    // Add terminal "/".
105
    $this->rootLength = Unicode::strlen(DRUPAL_ROOT);
106
107
  }
108
109
  /**
110
   * Controller.
111
   *
112
   * @return array
113
   *   A render array.
114
   */
115
  public function build(Request $request) {
116
    $count = $this->watchdog->templatesCount();
117
    $page = $this->setupPager($request, $count);
118
119
    $ret = [
120
      'filter_form' => $this->formBuilder->getForm('Drupal\mongodb_watchdog\Form\OverviewFilterForm'),
121
      'rows' => $this->buildRows($page),
122
      'pager' => [
123
        '#type' => 'pager',
124
      ],
125
      '#attached' => [
126
        'library' => ['mongodb_watchdog/styling'],
127
      ],
128
    ];
129
130
    return $ret;
131
  }
132
133
  /**
134
   * Build a table from the event rows.
135
   *
136
   * @param int $page
137
   *   The number of the page to display.
138
   *
139
   * @return array<string,array|string>
140
   *   A render array.
141
   */
142
  public function buildRows($page) {
143
    $header = [
144
      t('#'),
145
      t('Latest'),
146
      t('Severity'),
147
      t('Type'),
148
      t('Message'),
149
      t('Source'),
150
    ];
151
    $rows = [];
152
    $levels = RfcLogLevel::getLevels();
153
    $filters = $_SESSION[OverviewFilterForm::SESSION_KEY] ?? NULL;
154
    $skip = $page * $this->itemsPerPage;
155
    $limit = $this->itemsPerPage;
156
    $cursor = $this->watchdog->templates($filters['type'] ?? [], $filters['severity'] ?? [], $skip, $limit);
157
158
    /** @var \Drupal\mongodb_watchdog\EventTemplate $template */
159
    foreach ($cursor as $template) {
160
      $row = [];
161
      $row[] = $template->count;
162
      $row[] = $this->dateFormatter->format($template->changed, 'short');
163
      $row[] = [
164
        'class' => static::SEVERITY_CLASSES[$template->severity],
165
        'data' => $levels[$template->severity],
166
      ];
167
      $row[] = $template->type;
168
      $row[] = $this->getEventLink($template);
169
      $row[] = [
170
        'data' => $this->getEventSource($template, $row),
171
      ];
172
173
      $rows[] = $row;
174
    }
175
176
    $ret = [
177
      '#type' => 'table',
178
      '#header' => $header,
179
      '#rows' => $rows,
180
    ];
181
182
    return $ret;
183
  }
184
185
  /**
186
   * {@inheritdoc}
187
   */
188
  public static function create(ContainerInterface $container) {
189
    /** @var \Psr\Log\LoggerInterface $logger */
190
    $logger = $container->get('logger.channel.mongodb_watchdog');
191
192
    /** @var \Drupal\mongodb_watchdog\Logger $watchdog */
193
    $watchdog = $container->get('mongodb.logger');
194
195
    /** @var \Drupal\Core\Config\ImmutableConfig $config */
196
    $config = $container->get('config.factory')->get('mongodb_watchdog.settings');
197
198
    /** @var \Drupal\Core\Datetime\DateFormatterInterface $date_formatter */
199
    $date_formatter = $container->get('date.formatter');
200
201
    /** @var \Drupal\Core\Form\FormBuilderInterface $form_builder */
202
    $form_builder = $container->get('form_builder');
203
204
    /** @var \Drupal\Core\Extension\ModuleHandlerInterface $module_handler */
205
    $module_handler = $container->get('module_handler');
206
207
    return new static($logger, $watchdog, $config, $module_handler, $form_builder, $date_formatter);
208
  }
209
210
  /**
211
   * Build the link to the event or top report for the event template.
212
   *
213
   * @param \Drupal\mongodb_watchdog\EventTemplate $template
214
   *   The event template for which to buildl the link.
215
   *
216
   * @return string
217
   *   An internal link in string form.
218
   */
219
  protected function getEventLink(EventTemplate $template) {
220
    switch ($template->type) {
221
      case 'page not found':
222
        $cell = Link::createFromRoute(t('( Top 404 )'), 'mongodb_watchdog.reports.top404');
223
        break;
224
225
      case 'access denied':
226
        $cell = Link::createFromRoute(t('( Top 403 )'), 'mongodb_watchdog.reports.top403');
227
        break;
228
229
      // Limited-length message.
230
      default:
0 ignored issues
show
Coding Style introduced by
Blank lines are not allowed after DEFAULT statements
Loading history...
231
        $message = Unicode::truncate(strip_tags(SafeMarkup::format($template->message, [])), 56, TRUE, TRUE);
232
        $cell = Link::createFromRoute($message, 'mongodb_watchdog.reports.detail', [
233
          'event_template' => $template->_id,
234
        ]);
235
        break;
236
    }
237
238
    return $cell;
239
  }
240
241
  /**
242
   * Get the location in source code where the event was logged.
243
   *
244
   * @param \Drupal\mongodb_watchdog\EventTemplate $template
245
   *   The template for which to find a source location.
246
   *
247
   * @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...
248
   *   A render array for the source location, possibly empty or wrong.
249
   */
250
  protected function getEventSource(EventTemplate $template) {
251
    $cell = ['#markup' => ''];
252
253
    if (in_array($template->type, TopController::TYPES)) {
254
      return $cell;
255
    }
256
257
    $event_collection = $this->watchdog->eventCollection($template->_id);
258
    $event = $event_collection->findOne([], static::EVENT_TYPE_MAP);
259
    if (!($event instanceof Event)) {
260
      return $cell;
261
    }
262
263
    $file = $event->variables['%file'] ?? '';
264
    if ($file && strncmp($file, DRUPAL_ROOT, $this->rootLength) === 0) {
265
      $hover = Unicode::substr($file, $this->rootLength + 1);
266
      $file = Unicode::truncate(basename($file), 30);
267
    }
268
    else {
269
      $hover = NULL;
270
    }
271
272
    $line = $event->variables['%line'] ?? NULL;
273
    $cell = [
274
      '#type' => 'html_tag',
275
      '#tag' => 'span',
276
      '#value' => "${file}#${line}",
277
    ];
278
279
    if ($hover) {
280
      $cell['#attributes'] = [
281
        'class' => 'mongodb_watchdog__code_path',
282
        'title' => $hover,
283
      ];
284
    }
285
286
    return $cell;
287
  }
288
289
}
290