Completed
Pull Request — 8.x-2.x (#20)
by Frédéric G.
03:56 queued 44s
created

OverviewController::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 14
c 1
b 0
f 0
nc 1
nop 6
dl 0
loc 19
rs 9.4285
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\Controller\ControllerBase;
8
use Drupal\Core\Datetime\DateFormatterInterface;
9
use Drupal\Core\Link;
10
use Drupal\Core\Logger\RfcLogLevel;
11
use Drupal\mongodb_watchdog\Event;
12
use Drupal\mongodb_watchdog\EventTemplate;
13
use Drupal\mongodb_watchdog\Form\OverviewFilterForm;
14
use Drupal\mongodb_watchdog\Logger;
15
use Psr\Log\LoggerInterface;
16
use Psr\Log\LogLevel;
17
use Symfony\Component\DependencyInjection\ContainerInterface;
18
use Drupal\Core\Extension\ModuleHandlerInterface;
19
use Drupal\Core\Form\FormBuilderInterface;
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 items_per_page configuration value.
61
   *
62
   * @var int
63
   */
64
  protected $itemsPerPage;
65
66
  /**
67
   * The core logger channel, to log intervening events.
68
   *
69
   * @var \Psr\Log\LoggerInterface
70
   */
71
  protected $logger;
72
73
  /**
74
   * The module handler service.
75
   *
76
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
77
   */
78
  protected $moduleHandler;
79
80
  /**
81
   * The length of the disk path to DRUPAL_ROOT.
82
   *
83
   * @var int
84
   *
85
   * @see \Drupal\mongodb_watchdog\Controller\OverviewController::getEventSource()
86
   */
87
  protected $rootLength;
88
89
  /**
90
   * The MongoDB logger, to load events.
91
   *
92
   * @var \Drupal\mongodb_watchdog\Logger
93
   */
94
  protected $watchdog;
95
96
  /**
97
   * Constructor.
98
   *
99
   * @param \Psr\Log\LoggerInterface $logger
100
   *   The logger service, to log intervening events.
101
   * @param \Drupal\mongodb_watchdog\Logger $watchdog
102
   *   The MongoDB logger, to load stored events.
103
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
104
   *   A module handler.
105
   * @param \Drupal\Core\Form\FormBuilderInterface $form_builder
106
   *   The form builder service.
107
   * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
108
   *   The core date_formatter service.
109
   * @param int $items_per_page
110
   *   The items_per_page configuration value.
111
   */
112
  public function __construct(
113
    LoggerInterface $logger,
114
    Logger $watchdog,
115
    ModuleHandlerInterface $module_handler,
116
    FormBuilderInterface $form_builder,
117
    DateFormatterInterface $date_formatter,
118
    $items_per_page) {
119
    $this->dateFormatter = $date_formatter;
120
    $this->formBuilder = $form_builder;
121
    $this->logger = $logger;
122
    $this->moduleHandler = $module_handler;
123
    $this->watchdog = $watchdog;
124
125
    $this->itemsPerPage = $items_per_page;
126
127
    // Add terminal "/".
128
    $this->rootLength = Unicode::strlen(DRUPAL_ROOT);
129
130
  }
131
132
  /**
133
   * {@inheritdoc}
134
   */
135
  public static function create(ContainerInterface $container) {
136
    /** @var \Drupal\Core\Datetime\DateFormatterInterface $date_formatter */
137
    $date_formatter = $container->get('date.formatter');
138
139
    /** @var \Drupal\Core\Form\FormBuilderInterface $form_builder */
140
    $form_builder = $container->get('form_builder');
141
142
    /** @var \Psr\Log\LoggerInterface $logger */
143
    $logger = $container->get('logger.channel.mongodb_watchdog');
144
145
    /** @var \Drupal\Core\Extension\ModuleHandlerInterface $module_handler */
146
    $module_handler = $container->get('module_handler');
147
148
    /** @var \Drupal\mongodb_watchdog\Logger $logger */
149
    $watchdog = $container->get('mongodb.logger');
150
151
    /** @var \Drupal\Core\Config\ConfigFactoryInterface $config_factory */
152
    $config_factory = $container->get('config.factory');
153
    $items_per_page = $config_factory->get('mongodb_watchdog.settings')->get('items_per_page');
154
155
    return new static($logger, $watchdog, $module_handler, $form_builder, $date_formatter, $items_per_page);
156
  }
157
158
  /**
159
   * Build the link to the event or top report for the event template.
160
   *
161
   * @param \Drupal\mongodb_watchdog\EventTemplate $template
162
   *   The event template for which to buildl the link.
163
   *
164
   * @return string
165
   *   An internal link in string form.
166
   */
167
  protected function getEventLink(EventTemplate $template) {
168
    switch ($template->type) {
169
      case 'page not found':
170
        $cell = Link::createFromRoute(t('( Top 404 )'), 'mongodb_watchdog.reports.top404');
171
        break;
172
173
      case 'access denied':
174
        $cell = Link::createFromRoute(t('( Top 403 )'), 'mongodb_watchdog.reports.top403');
175
        break;
176
177
      default:
178
        // Limited-length message.
179
        $message = Unicode::truncate(strip_tags(SafeMarkup::format($template->message, [])), 56, TRUE, TRUE);
180
        $cell = Link::createFromRoute($message, 'mongodb_watchdog.reports.detail', [
181
          'event_template' => $template->_id,
182
        ]);
183
        break;
184
    }
185
186
    return $cell;
187
  }
188
189
  /**
190
   * Get the location in source code where the event was logged.
191
   *
192
   * @param \Drupal\mongodb_watchdog\EventTemplate $template
193
   *   The template for which to find a source location.
194
   *
195
   * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be string|array<string,string|array>?

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...
196
   *   A render array for the source location, possibly empty or wrong.
197
   */
198
  protected function getEventSource(EventTemplate $template) {
199
    if (in_array($template->type, TopController::TYPES)) {
200
      return '';
201
    }
202
203
    $event_collection = $this->watchdog->eventCollection($template->_id);
204
    $event = $event_collection->findOne([], static::EVENT_TYPE_MAP);
205
    if (!($event instanceof Event)) {
206
      return '';
207
    }
208
209
    $file = $event->variables['%file'] ?? '';
1 ignored issue
show
introduced by
Expected 1 space after "?"; 0 found
Loading history...
210
    if ($file && strncmp($file, DRUPAL_ROOT, $this->rootLength) === 0) {
211
      $hover = Unicode::substr($file, $this->rootLength + 1);
212
      $file = Unicode::truncate(basename($file), 30);
213
    }
214
    else {
215
      $hover = NULL;
216
    }
217
218
    $line = $event->variables['%line'] ?? NULL;
1 ignored issue
show
introduced by
Expected 1 space after "?"; 0 found
Loading history...
219
    $cell = [
220
      '#type' => 'html_tag',
221
      '#tag' => 'span',
222
      '#value' => "${file}#${line}",
223
    ];
224
225
    if ($hover) {
226
      $cell['#attributes'] = [
227
        'class' => 'mongodb_watchdog__code_path',
228
        'title' => $hover,
229
      ];
230
    }
231
232
    return $cell;
233
  }
234
235
  /**
236
   * Controller for mongodb_watchdog.overview.
237
   *
238
   * @return array
239
   *   A render array.
240
   */
241
  public function overview(Request $request) {
242
    $page = $this->setupPager($request);
243
244
    $ret = [
245
      'filter_form' => $this->formBuilder->getForm('Drupal\mongodb_watchdog\Form\OverviewFilterForm'),
246
      'rows' => $this->overviewRows($page),
247
      'pager' => [
248
        '#type' => 'pager',
249
      ],
250
      '#attached' => [
251
        'library' => ['mongodb_watchdog/styling'],
252
      ],
253
    ];
254
255
    return $ret;
256
  }
257
258
  /**
259
   * Build a table from the event rows.
260
   *
261
   * @param int $page
262
   *   The number of the page to display.
263
   *
264
   * @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...
265
   *   A render array.
266
   */
267
  public function overviewRows($page) {
268
    $header = [
269
      t('#'),
270
      t('Latest'),
271
      t('Severity'),
272
      t('Type'),
273
      t('Message'),
274
      t('Source'),
275
    ];
276
    $rows = [];
277
    $levels = RfcLogLevel::getLevels();
278
    $filters = $_SESSION[OverviewFilterForm::SESSION_KEY] ?? NULL;
1 ignored issue
show
introduced by
Expected 1 space after "?"; 0 found
Loading history...
279
    $skip = $page * $this->itemsPerPage;
280
    $limit = $this->itemsPerPage;
281
    $cursor = $this->watchdog->templates($filters['type'] ?? [], $filters['severity'] ?? [], $skip, $limit);
1 ignored issue
show
introduced by
Expected 1 space after "?"; 0 found
Loading history...
282
283
    /** @var \Drupal\mongodb_watchdog\EventTemplate $template */
284
    foreach ($cursor as $template) {
285
      $row = [];
286
      $row[] = $template->count;
287
      $row[] = $this->dateFormatter->format($template->changed, 'short');
288
      $row[] = [
289
        'class' => static::SEVERITY_CLASSES[$template->severity],
290
        'data' => $levels[$template->severity],
291
      ];
292
      $row[] = $template->type;
293
      $row[] = $this->getEventLink($template);
294
      $row[] = [
295
        'data' => $this->getEventSource($template, $row),
296
      ];
297
298
      $rows[] = $row;
299
    }
300
301
    return [
302
      '#type' => 'table',
303
      '#header' => $header,
304
      '#rows' => $rows,
305
    ];
306
  }
307
308
  /**
309
   * Set up the templates pager.
310
   *
311
   * @param \Symfony\Component\HttpFoundation\Request $request
312
   *   The current request.
313
   *
314
   * @return int
315
   *   The number of the page to display, starting at 0.
316
   */
317
  public function setupPager(Request $request) {
318
    $count = $this->watchdog->templatesCount();
319
    $height = $this->itemsPerPage;
320
    pager_default_initialize($count, $height);
321
322
    $page = intval($request->query->get('page'));
323
    if ($page < 0) {
324
      $page = 0;
325
    }
326
    else {
327
      $page_max = intval(min(ceil($count / $height), PHP_INT_MAX));
328
      if ($page > $page_max) {
329
        $page = $page_max;
330
      }
331
    }
332
333
    return $page;
334
  }
335
336
}
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...
337